3

我是 Xamarin 的新手,想创建一个包含多个页面的应用程序,这些页面通过按钮单击导航到。我已经弄清楚如何通过代码导航到所需的页面,但我正在努力隐藏选项卡以禁用用户导航。

我正在使用 TabbedPage 有我的主页,然后添加 8 个 NavigationPages 作为子级。

如何隐藏标签?

4

5 回答 5

4

若要在 Xamarin.Forms 中隐藏选项卡,您需要在本机项目中包含自定义呈现器。我没有使用 UWP atm,所以只是发布了 iOS 和 Android 的渲染器,它们完全隐藏了选项卡栏。更改我的命名空间并考虑可能将选项卡式页面子类化,这样您就不会隐藏应用程序中的所有选项卡,而只是选择的选项卡。

iOS 渲染器:

using System;
using AppoMobi.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;

[assembly: ExportRenderer(typeof(TabbedPage), typeof(HiddenTabbedPageRenderer))]
namespace AppoMobi.iOS
{   
    //***************************************************************************
    public class HiddenTabbedPageRenderer : TabbedRenderer
    //***************************************************************************
    {

        private UITabBarController tabbarController { get; set; }
        private TabbedPage CurrentTabbedPage { get; set; }

        //-------------------------------------------------------------
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        //-------------------------------------------------------------
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                //release any stuff here
            }

            if (e.NewElement != null)
            {
                tabbarController = (UITabBarController) this.ViewController;
                CurrentTabbedPage = (TabbedPage) e.NewElement;
            }
            else
            {
                CurrentTabbedPage = (TabbedPage) e.OldElement;
            }

            //the following commented code is not working
            //as Forms as it just leaves empty white space
            //instead of hidden tabbedbar:     
            //       if (tabbarController != null)
            //         tabbarController.TabBar.Hidden = true;
        }

        //just hide tabbar by setting its height to zero
        // credits:
        // https://stackoverflow.com/a/26255545/7149454
        // "how to change UITabBar height"
        private nfloat newHeight = 0; //change tabbed bar height to this value
        //-------------------------------------------------------------------
        public override void ViewWillLayoutSubviews()
        //-------------------------------------------------------------------
        {
            if (tabbarController != null)
            {
                var tabFrame = tabbarController.TabBar.Frame; //self.TabBar is IBOutlet of your TabBar
                tabFrame.Height = newHeight;
                tabFrame.Offset(0, tabbarController.View.Frame.Height - newHeight);
                tabbarController.TabBar.Frame = tabFrame;
            }
            base.ViewWillLayoutSubviews();
        }
    }
}

安卓渲染器:

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using System;
using Android.Content;
using Android.Support.Design.Widget;
using Android.Support.V4.View;
using Android.Views;
using AppoMobi.Droid;
using Xamarin.Forms.Platform.Android.AppCompat;

[assembly: ExportRenderer(typeof(TabbedPage), typeof(MyTabbedRenderer))]
namespace AppoMobi.Droid
{
    //****************************************************
    public class MyTabbedRenderer : TabbedPageRenderer, TabLayout.IOnTabSelectedListener
    //****************************************************
    {

        private TabLayout TabsLayout { get; set; }
        private ViewPager PagerLayout { get; set; }
        private NiftyTabbedPage CurrentTabbedPage { get; set; }

        //-------------------------------------------------------------------
        public MyTabbedRenderer(Context context) : base(context)
        //-------------------------------------------------------------------
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                //cleanup here
            }

            if (e.NewElement != null)
            {
                CurrentTabbedPage = (NiftyTabbedPage)e.NewElement;
            }
            else
                CurrentTabbedPage = (NiftyTabbedPage)e.OldElement;

            //find the pager and tabs
            for (int i = 0; i < ChildCount; ++i)
            {
                Android.Views.View view = (Android.Views.View)GetChildAt(i);
                if (view is TabLayout)
                    TabsLayout = (TabLayout)view;
                else
                if (view is ViewPager) PagerLayout = (ViewPager)view;
            }

        }


        //-------------------------------------------------------------------------------
        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        //-------------------------------------------------------------------------------    
        {
            TabsLayout.Visibility = ViewStates.Gone;

            base.OnLayout(changed, l, t, r, b);
        }    
    }


}
于 2018-02-07T17:20:53.640 回答
1

我喜欢这里提供的 ZaneCampbell 的解决方案。它可以工作,很简单,并且不需要自定义渲染器。用他自己的话来说:

我只是将我的 TabbedPage 嵌入到 NavigationPage 中,然后当我将选项卡添加到 TabbedPage 时,我将一个操作传递给必要的选项卡,允许它们将页面推送到 NavigationPage。经过测试并在 iOS 和 Android 上运行。

然后是代码:

public class TabControllerPage : TabbedPage
{
    public TabControllerPage()
    {
        // This hides the navigation page's navigation bar as it is not needed
        NavigationPage.SetHasNavigationBar(this, false);

        // Create tab page and pass PushPage action to it
        var testPage = new TestPage {
            PushPage = (page) => {
                Navigation.PushAsync(page, true);
            }
        };

        // Add as many tabs as you like here
        AddTab(testPage, "Tab 1", true, "tab_1_icon.png");
    }

    void AddTab(Page page, string title, bool inNav, string icon = null)
    {
        // This sets the NavigationBar title
        page.Title = title;

        if (inNav)
        {
            var navigationPage = new NavigationPage(page);
            if (icon != null)
            {
                navigationPage.Icon = icon;
            }
            // This sets the tab labels
            navigationPage.Title = title;
            Children.Add(navigationPage);
        }
        else
        {
            Children.Add(page);
        }
    }
}

public partial class TestPage : ContentPage
{
    public Action<ContentPage> PushPage;

    public TestPage()
    {
        InitializeComponent();
    }

    // Call this method when ever you need to push a page onto the navigation page and hide the tabbed page.
    void NavigateToPage(ContentPage page)
    {
        PushPage?.Invoke(page);
    }
}
于 2019-04-22T19:45:27.693 回答
0

您只需执行此操作即可简单地删除或隐藏您不想要的页面。

this.Children.Remove(Page you want to remove);
于 2019-11-06T21:32:10.157 回答
0

在我的自定义渲染器中,我能够像这样隐藏标签导航栏。

 protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            tabbedPage = e.NewElement as Xamarin.Forms.TabbedPage;
            bottomNavigationView = (GetChildAt(0) as Android.Widget.RelativeLayout).GetChildAt(1) as BottomNavigationView;
            bottomNavigationView.NavigationItemSelected += BottomNavigationView_NavigationItemSelected;

            //Call to change the font
            ChangeFont();
        }

        if (e.OldElement != null)
        {
            bottomNavigationView.NavigationItemSelected -= BottomNavigationView_NavigationItemSelected;
        }

        bottomNavigationView.Visibility = ViewStates.Gone;
    }
于 2020-07-10T10:23:07.727 回答
-1

如何隐藏标签?

在我看来你不应该。

对于您描述的导航方案,选项卡式页面根本不是正确的手段,无论是从技术上还是从用户体验的角度来看。

也许实现所需导航方案的最简单方法是使用 a NavigationPage(参见此处此处HasNavigationBar)并通过将属性设置为来隐藏导航栏false

// in App.xaml.cs

public App()
{
    InitializeComponent();
    MainPage = new NavigationPage(new FirstPage())
    {
        HasNavigationBar = false;
    };
}

您可以从您的页面访问Application.Current、获取NavigationPage和导航

public void Button_OnPress(object sender, EventArgs e)
{
    var navigationPage = Application.Current.MainPage as NavigationPage;
    if(navigationPage != null)
    {
        navigationPage.PushAsync(new WhatEverPage());
    }
}

备注:虽然你可以这样做,但并不意味着你应该这样做。我强烈建议使用 Prism 之类的 MVVM 框架并使用 prisms 进行导航INavigationService。通过这种方式,您可以保持页面松散耦合,因为INavigationService不使用页面实例,而是使用它们的名称并使用 DI 容器解析它们。

于 2018-02-07T11:35:38.220 回答