Xamarin.Forms.Shell: как получить высоту нижней панели вкладок?

Я работаю над приложением Xamarin.Forms.Shell, используя нижнюю часть TabBar по умолчанию, и мне нужно знать TabBar высоту, чтобы настроить некоторые элементы.

Я нашел способ получить StatusBar height на обеих платформах там, но я не нашел решения для TabBar.

Является ли это возможным? Я нашел только запросы об изменении высоты TabBar в стеке...


person Gold.strike    schedule 18.11.2020    source источник
comment
Это работает сейчас?   -  person Lucas Zhang    schedule 20.11.2020


Ответы (2)


Мы могли бы получить высоту с помощью Custom Renderer.

в AppShell

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

  //...
}

в iOS-проекте

Вариант 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)
        {
           
        }
    }
}

Вариант 2:

На самом деле высота UITabbar в iOS является фиксированным значением. На iPhone 8 и более ранних версиях — 49, а iPhone X и более поздних версиях (полноэкранный режим) будет иметь дополнительную высоту основания safeArea. Поэтому, если вы просто хотите получить его (не нужно устанавливать высоту), вы можете получить его напрямую, используя DependencyService, как показано ниже.

AppShell.TabHeight = 49 + UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom;

в 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);
        }
    }
}
person Lucas Zhang    schedule 18.11.2020
comment
Привет @ Лукас. Кажется, это работает на iOS, но я теряю стиль, указанный в Shell.xaml для цвета текста TabBar. На Android высота не восстанавливается, пока я не изменю вкладку хотя бы один раз. Поскольку мне нужна эта информация на домашней странице, я не могу использовать это решение. Кроме того, я также теряю стиль по умолчанию. - person Gold.strike; 18.11.2020
comment
Вы можете переустановить стиль после получения высоты. - person Lucas Zhang; 18.11.2020

Насколько мне известно, в Xamarin.Forms невозможно (пока?) получить TabBar Height, поэтому вам, возможно, придется собирать эту информацию для каждой платформы. . Затем, используя DependencyService, вы сможете сделать эту информацию доступной из общего кода Xamarin.Forms. Итак, давайте посмотрим, как это сделать:

iOS

Для iOS уже были опубликованы ответы, такие как это, чтобы объяснить, как это можно сделать.

Андроид

Для Android вы можете получить высоту TabBar следующим образом.

  • Создайте Интерфейс для зависимости

Примечание. Этот интерфейс также следует использовать в части iOS;)

namespace Tabbarheight
{
    public interface IDisplayHeights
    {
        float GetTabBarHeight();
    }
}
  • Создайте в Android класс, который реализует этот интерфейс и возвращает нужное значение.

(спасибо @LucasZhang-MSFT за строку идентификатора!)

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;

        }
    }
}

где Activity задается из MainActivity.cs следующим образом

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;

    };

}

В приведенном выше решении я определил Label (метку) просто для того, чтобы попытаться продемонстрировать точность полученного значения Height TabBar, установив высоту Label.

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

На моей стороне этикетка выглядит так:

введите здесь описание изображения

person Deczaloth    schedule 18.11.2020