Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Forms.Shell: how to get the bottom TabBar height?

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...

like image 957
Gold.strike Avatar asked Nov 18 '20 11:11

Gold.strike


2 Answers

We could get the height by using Custom Renderer

in AppShell

public partial class AppShell : Xamarin.Forms.Shell
{
   public static double TabHeight { get; set; }

  //...
}

in iOS project

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;

in Android

 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);
        }
    }
}
like image 199
Lucas Zhang Avatar answered Nov 14 '22 20:11

Lucas Zhang


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:

iOS

For iOS, there have already been published answers like this to explain how this can be done.

Android

For Android you can retrieve the TabBar height as follows

  • Create Interface for Dependency

Note: This interface should also be used on the iOS part ;)

namespace Tabbarheight
{
    public interface IDisplayHeights
    {
        float GetTabBarHeight();
    }
}
  • Create a class in Android that implements that interface and returns the desired value

(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());
}
  • And finally, you can consume this as follows
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:

enter image description here

like image 30
deczaloth Avatar answered Nov 14 '22 22:11

deczaloth