我在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损坏,并且不会恢复标签栏。
我认为唯一可行的解决办法就是让这个属性起作用:UIViewController.HidesBottomBarWhenPushed
。但是,我不知道该怎么做,因为在渲染器中设置/覆盖它不起作用。
有没有人设法成功展示&隐藏TabBar?
答案 0 :(得分: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();
}
}
}
}
最终结果:
答案 1 :(得分:2)
我尝试过:
创建ContentPage的子类并在其中创建BindableProperty(如HidesBottomBarWhenPushed
)。我在PageRenderer中设置ViewController.hidesBottomBarWhenPushed
但它不起作用,虽然我可以获得此属性的值。
在PageRenderer的初始构造函数中设置this.hidesBottomBarWhenPushed
,仍然没有运气。
我认为hidesBottomBarWhenPushed
一定有问题,我们无法通过这种方式隐藏tabbar。作为一种临时且简单的解决方法,我更改了PageRenderer中TabBarController.TabBar
的可见性
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上禁用动画,问题就消失了。
测试:
答案 2 :(得分:0)
我在将选项卡栏绘制到屏幕上之前需要隐藏它时遇到了一个问题。
Wojciech Kulik的解决方案对我有所帮助,但导航到选项卡式页面时它开始闪烁。
以下代码解决了我的问题。希望对您有帮助。 将其放在TabbedRenderer派生类中
public override void ViewWillLayoutSubviews()
{
OnTabBarHidden(true); // Hide before the page appear
}
答案 3 :(得分:0)
有一种不需要任何渲染的解决方案,并且可以在Android和iOS上使用。
将TabbedPage
包裹在NavigationPage
中,这样您的应用程序的结构就会变得
在TabbedPage上,您必须隐藏“根”导航页的导航栏,否则,您将有2个导航栏。
<TabbedPage
...
HasNavigationBar="False">
如果您使用'root'NavigationPage
推送页面,则标签栏将被隐藏,并且底部没有空格。
在以下位置查看我的示例: https://github.com/Jfcobuss/HideTabbarExample/tree/master/HideTabbarExample