3

I am new to Xamarin and would like to create a application with multiple pages that are navigated to through button click. I have already worked out how to navigate to the desired page through code but I am struggling to hide the tabs to disable navigation by the user.

I am using a TabbedPage has my main page and then add 8 NavigationPages as children.

How to I hide Tabs?

Pomster
  • 14,567
  • 55
  • 128
  • 204

5 Answers5

5

To hide tabs in Xamarin.Forms you need to include custom renderers in your native projects. I'm not working with UWP atm so just posting renderers for iOS and Android, they hide tabbed bars completely. Change my namespace and think about maybe subclass the tabbed page so you don't hide all your tabs in the app but just chosen ones.

iOS renderer:

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();
        }
    }
}

Android renderer:

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);
        }    
    }


}
Nick Kovalsky
  • 5,378
  • 2
  • 23
  • 50
1

I like ZaneCampbell's solution provided here. It works, it's simple and it doesn't require a custom renderer. In his own words:

I simply embedded my TabbedPage in a NavigationPage and then when i add my tabs to the TabbedPage i pass an action to the necessary tabs which allows them to push a page onto the NavigationPage. Tested and works on both iOS and Android.

And then the code:

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);
    }
}
Giuliana
  • 99
  • 1
  • 6
0

You can simply remove or hide the pages that you don't want by simply doing this.

this.Children.Remove(Page you want to remove);
0

In my custom renderer, I was able to hide the tab navigation bar like this.

 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;
    }
Akif Patel
  • 23
  • 3
-1

How to I hide Tabs?

In my opinion you should not.

For the navigation scheme you described, tabbed pages are not at all the right means, neither technically, nor from a UX perspective.

Maybe the easiest way to achieve the desired navigation scheme will be to use a NavigationPage (see here and here) and hide the navigation bar by setting the HasNavigationBar property to false

// in App.xaml.cs

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

From your pages you can access Application.Current, get the NavigationPage and navigate

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

Remarks: Though you can do it that way, it doesn't mean you should. I'd strongly suggest to use a MVVM-framework like Prism and navigate with prisms INavigationService. This way you keep your pages loosely coupled, since INavigationService does not takes instances of pages, but their names and resolves them with a DI container.

Paul Kertscher
  • 9,416
  • 5
  • 32
  • 57
  • That TL/DR is inappropriate. I have a use case that requires exactly this functionality. My app has a main process that pushes pages onto the stack and pops to root at the end of the process. I have supporting features that are accessed using tabs on the root page. The tabs need to be hidden for the main process and only visible on the root. – David Clarke Aug 24 '18 at 01:10