I want to add a custom view above the tabbar in Xamarin Forms Shell (iOS and Android) to implement an audio player that is always visible.
For Android I looked into this blog post about customizing the tabbar on Android (https://www.andrewhoefling.com/Blog/Post/xamarin-forms-shell-customizing-the-tabbar-android), and added an extra layout with id '@+id/bottomtab.view' to my customized BottomTabLayout.axml.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/bottomtab.navarea"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="fill"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:id="@+id/bottomtab.view"
android:layout_width="match_parent"
android:background="@drawable/abc_action_bar_item_background_material"
android:layout_height="70dp" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomtab.tabbar"
android:theme="@style/Widget.Design.BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/bottomtab.tabbar.container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom" />
</FrameLayout>
In my custom ShellItemRenderer of my TabBar subclass I want to add the xaml to the layout, but that doesn't work.
using Xamarin.Forms;
namespace TodosSample.Controls
{
public class TodoTabBar : TabBar
{
public Tab LargeTab { get; set; }
public View View { get; set; }
}
}
XAML
<c:TodoTabBar.View>
<Grid BackgroundColor="#232026" Padding="10">
<Grid BackgroundColor="PaleVioletRed">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid BackgroundColor="#092C33" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<Button BackgroundColor="IndianRed" Text="Click me" Clicked="Button_Clicked"/>
<Grid Grid.Column="1" BackgroundColor="Yellow">
<Label Text="Guy en Marinda" />
</Grid>
<Grid Grid.Column="2" WidthRequest="50" HeightRequest="50" BackgroundColor="Aqua" />
</Grid>
</c:TodoTabBar.View>
For some reason the background of the outer grid is applied, like you can see in the screenshot, but the contents are not shown. I don't know how to apply the correct dimensions to make the grid and the children take the full width of the screen.
// Rendering part in the custom TodoShellItemRenderer. This code is being called
private void SetupView()
{
var todoTabBar = (TodoTabBar)ShellItem;
var renderer = Platform.CreateRendererWithContext(todoTabBar.View, Context);
renderer.Tracker.UpdateLayout();
var nativeView = renderer.View;
nativeView.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
int width = ViewGroup.LayoutParams.MatchParent;
int height = 70;
todoTabBar.View.Layout(new Xamarin.Forms.Rectangle(0, 0, width, height));
nativeView.Layout(0, 0, width, height);
_view.RemoveAllViews();
_view.AddView(nativeView);
nativeView.ForceLayout();
}
I like the idea to define the contents of the view in xaml to be able to setup the bindings and such. How can I render the view correctly in the layout?
===============
Update 2020-11-12
I have changed my code to implement Leo's suggestion, but changed it to use the bottomtab.view layout in the android xml. (I use the framelayout bottomtab.tabbar.container for a kind of floating button, that works fine).
However, it looks like the width of the view above the tab bar is incorrect. In the screenshot you see that the Pink BoxView doesn't have a right side, it looks like the inner gridview (white background) is too wide. The bottom black border of the screenshot is the tabbar that I redacted.
This is my definition of the extra view in xaml:
<Grid BackgroundColor="HotPink">
<BoxView BackgroundColor="Pink" />
<Grid BackgroundColor="White" Margin="5">
</Grid>
</Grid>
This is the adapted SetupView method
private void SetupTopView()
{
var todoTabBar = (SearchTabBar)ShellItem;
var height = 70;
var width = (int)Resources.DisplayMetrics.WidthPixels;
Rectangle size = new Rectangle(0, 0, width, height);
todoTabBar.ExtraView.Layout(size);
var renderer = Platform.CreateRendererWithContext(todoTabBar.ExtraView, Context);
renderer.Tracker.UpdateLayout();
var nativeView = renderer.View;
var layout = new FrameLayout(Context);
layout.AddView(nativeView);
var lp = new FrameLayout.LayoutParams(width, height * (int)Resources.DisplayMetrics.Density);
_bottomView.Measure((int)MeasureSpecMode.Unspecified, (int)MeasureSpecMode.Unspecified);
lp.BottomMargin = _bottomView.MeasuredHeight;
layout.LayoutParameters = lp;
_extraViewContainer.RemoveAllViews();
_extraViewContainer.AddView(layout);
}
Any suggestion to let it use the correct width? Or is my xaml definition incorrect?