首页 文章

如何在Xamarin.Forms中隐藏Tab Bar?

提问于
浏览
2

我在iOS上的Xamarin.Forms中使用 TabbedPage 进行了最后几天的努力 . 我发现了一些像这样的解决方案:https://forums.xamarin.com/discussion/20901/hide-tab-bar-on-push

但是,它们都不是很好 . 我也尝试子类 TabbedRenderer 并将TabBar高度设置为0.它可以工作,但如果我在 NavigationPage.Pushed 事件处理程序中隐藏TabBar,则会有一些延迟,例如TableView底部有空白 .

如果我试图覆盖 NavigationRenderer 并在 PushViewController / PopViewController 方法中隐藏/显示标签栏,它有时会失败 . 例如,如果我来回快速导航,则不会调用方法 PopViewController ,导致NavigationStack损坏,并且不会恢复Tab Bar .

我认为唯一的好办法是使这个属性有效: UIViewController.HidesBottomBarWhenPushed . 但是,我不知道该怎么做,因为在渲染器中设置/覆盖它不起作用 .

有没有人设法成功展示和隐藏TabBar?

2 回答

  • 4

    我设法实现了一个解决方案,在隐藏 TabBar 后修复了空白区域的问题 . 您可以在this article中阅读有关它的更多详细信息 .

    要解决这个问题,我们只需要布局所有 ChildViewControllers . 这是我自定义 TabbedPage 及其 TabbedPageRenderer 的示例实现 .

    HideableTabbedPage.cs:

    using System;
    using Xamarin.Forms;
    
    namespace HideTabBar.Controls
    {
        public class HideableTabbedPage : TabbedPage
        {
            public static readonly BindableProperty IsHiddenProperty =
                BindableProperty.Create(nameof(IsHidden), typeof(bool), typeof(HideableTabbedPage), false);
    
            public bool IsHidden
            {
                get { return (bool)GetValue(IsHiddenProperty); }
                set { SetValue(IsHiddenProperty, value); }
            }
        }
    }
    

    HideableTabbedPageRenderer.cs:

    using System;
    using System.ComponentModel;
    using System.Threading.Tasks;
    using HideTabBar.Controls;
    using HideTabBar.iOS.CustomRenderer;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: ExportRenderer(typeof(HideableTabbedPage), typeof(HideableTabbedPageRenderer))]
    namespace HideTabBar.iOS.CustomRenderer
    {
        public class HideableTabbedPageRenderer : TabbedRenderer
        {
            private bool disposed;
            private const int TabBarHeight = 49;
    
            protected override void OnElementChanged(VisualElementChangedEventArgs e)
            {
                base.OnElementChanged(e);
    
                if (e.OldElement == null)
                {
                    this.Tabbed.PropertyChanged += Tabbed_PropertyChanged;
                }
            }
    
            private void Tabbed_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == HideableTabbedPage.IsHiddenProperty.PropertyName)
                {
                    this.OnTabBarHidden((this.Element as HideableTabbedPage).IsHidden);
                }
            }
    
            protected override void Dispose(bool disposing)
            {
                base.Dispose(disposing);
                this.disposed = true;
            }
    
            private async void OnTabBarHidden(bool isHidden)
            {
                if (this.disposed || this.Element == null || this.TabBar == null)
                {
                    return;
                }
    
                await this.SetTabBarVisibility(isHidden);
            }
    
            private async Task SetTabBarVisibility(bool hide)
            {
                this.TabBar.Opaque = false;
                if (hide)
                {
                    this.TabBar.Alpha = 0;
                }
    
                this.UpdateFrame(hide);
    
                // Show / Hide TabBar
                this.TabBar.Hidden = hide;
                this.RestoreFonts();
    
                // Animate appearing 
                if (!hide)
                {
                    await UIView.AnimateAsync(0.2f, () => this.TabBar.Alpha = 1);
                }
                this.TabBar.Opaque = true;
    
                this.ResizeViewControllers();
                this.RestoreFonts();
            }
    
            private void UpdateFrame(bool isHidden)
            {
                var tabFrame = this.TabBar.Frame;
                tabFrame.Height = isHidden ? 0 : TabBarHeight;
                this.TabBar.Frame = tabFrame;
            }
    
            private void RestoreFonts()
            {
                // Workaround to restore custom fonts:
    
                foreach (var item in this.TabBar.Items)
                {
                    var text = item.Title;
                    item.Title = "";
                    item.Title = text;
                }
            }
    
            private void ResizeViewControllers()
            {
                foreach (var child in this.ChildViewControllers)
                {
                    child.View.SetNeedsLayout();
                    child.View.SetNeedsDisplay();
                }
            }
        }
    }
    

    Final result:

    auto hiding tab bar

  • 2

    我尝试过的:

    • 创建ContentPage的子类并在其中创建BindableProperty(如 HidesBottomBarWhenPushed ) . 我在PageRenderer中设置 ViewController.hidesBottomBarWhenPushed 但它不起作用,虽然我可以得到这个属性的值 .

    • 在PageRenderer的初始构造函数中设置 this.hidesBottomBarWhenPushed ,仍然没有运气 .

    我认为 hidesBottomBarWhenPushed 一定有问题,我们不能用这种方式隐藏tabbar . 作为一个临时和简单的解决方法,我在PageRenderer中更改 TabBarController.TabBar 的Visible

    class PageiOS : PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
            if (this.NavigationController != null && this.TabBarController != null)
            {
                bool isRootVC = this.NavigationController.ViewControllers.Length == 1;
                ParentViewController.TabBarController.TabBar.Hidden = !isRootVC;
            }
        }
    }
    

    它的行为与上面所说的一样,底部有一些延迟和空白 . 我在push和pop上禁用了动画,问题就消失了 .

    测试:

    enter image description here

相关问题