I work on a Xamarin.Forms.Shell app using the default bottom TabBar
, and I need to know the TabBar
height to adjust some items.
I've found a way to get the StatusBar
height on both platforms there, but I didn't found a solution for the TabBar
.
Is it possible? I only found requests about changing the TabBar height on Stack...
We could get the height by using Custom Renderer
public partial class AppShell : Xamarin.Forms.Shell
{
public static double TabHeight { get; set; }
//...
}
Option 1:
using App33;
using App33.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(AppShell), typeof(ShellCustomRenderer))]
namespace App33.iOS
{
public class ShellCustomRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new TabBarAppearance();
}
}
public class TabBarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
base.ViewWillAppear(animated);
UITabBar myTabBar = this.TabBarController.TabBar;
myTabBar.TintColor = UIColor.Red;
myTabBar.BarTintColor = UIColor.LightGray;
//... you can set style like above in iOS
AppShell.TabHeight = myTabBar.Bounds.Height;
}
public void UpdateLayout(UITabBarController controller)
{
}
}
}
Option 2:
Actually, The height of UITabbar on iOS is a fixed value . On iPhone 8 and before is 49 and iPhone X and after(full-screen) will have an extra safeArea bottom height . So if you just want to get it (don't need to set the height) , you could get it directly by using DependencyService like following
AppShell.TabHeight = 49 + UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom;
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
// var hei=SupportActionBar.Height;
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
int resourceId =Resources.GetIdentifier("design_bottom_navigation_height", "dimen", this.PackageName);
int height = 0;
if (resourceId > 0)
{
height = Resources.GetDimensionPixelSize(resourceId);
AppShell.TabHeight = height;
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
As far as i know, in Xamarin.Forms it is not (yet?) possible to retrieve the TabBar
Height
, so you might have to go and collect that information per Platform. Then, making use of DependencyService
you would be able to make that information available from your Xamarin.Forms shared code. So, lets take a look at how to do it:
For iOS, there have already been published answers like this to explain how this can be done.
For Android you can retrieve the TabBar height as follows
Note: This interface should also be used on the iOS part ;)
namespace Tabbarheight
{
public interface IDisplayHeights
{
float GetTabBarHeight();
}
}
(thanks to @LucasZhang-MSFT for the identifier string!)
using Android.App;
using Tabbarheight.Droid;
using Xamarin.Forms;
[assembly: Dependency(typeof(AndroidDisplayHeights))]
namespace Tabbarheight.Droid
{
class AndroidDisplayHeights : IDisplayHeights
{
public static Activity Activity { get; set; }
public float GetTabBarHeight()
{
int resourceId = Activity.Resources.GetIdentifier("design_bottom_navigation_height", "dimen", Activity.PackageName);
int height = 0;
if (resourceId > 0)
{
height = (int)(Activity.Resources.GetDimensionPixelSize(resourceId) / Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density);
}
return height;
}
}
}
where Activity
is set from MainActivity.cs as follows
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
AndroidDisplayHeights.Activity = this;
LoadApplication(new App());
}
public AboutPage()
{
InitializeComponent();
SizeChanged += (s, a) =>
{
label.HeightRequest = DependencyService.Get<IDisplayHeights>().GetTabBarHeight();
label.BackgroundColor = Color.Red;
};
}
In the solution above i defined a Label
(label) simply to try to demonstrate the accuracy of the gotten TabBar
's Height
value by setting the Label
's height.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Tabbarheight.Views.AboutPage"
xmlns:vm="clr-namespace:Tabbarheight.ViewModels"
Title="{Binding Title}">
<StackLayout>
<Label x:Name="label">
<Label.Text>
<x:String>
Hola mundo
</x:String>
</Label.Text>
</Label>
</StackLayout>
</ContentPage>
The label looks like this on my side:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With