Quantcast
Viewing all articles
Browse latest Browse all 3

Auto hiding Tab Bar on navigation

Overview

In Xamarin.Forms on iOS it’s not as easy as it should be to hide TabBar on navigation. In native programming there is a property HidesBottomBarWhenPushed, unfortunately it doesn’t work with Xamarin.Forms.

The main idea to solve this issue is to set TabBar’s height to zero and hide it, but the problem is that frame modification causes a blank space in place of TabBar. You can see it below:

Image may be NSFW.
Clik here to view.
Blank space
Blank space

 

1. Custom TabbedPage implementation

To fix the solution above we need to layout all ChildViewControllers, so let’s start with implementing our HideableTabbedPage with IsHidden property and its Renderer:

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

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

 

2. Auto hiding implementation

Now to automatically hide TabBar we will use a custom Page implementation. To make it simple I assumed that Application.Current.MainPage is HideableTabbedPage. If you want to improve this solution, you can hide TabBar using for example MessagingCenter.

using Xamarin.Forms;

namespace HideTabBar.Controls
{
    public class TabDetailPage : ContentPage { }
}

using HideTabBar.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(TabDetailPage),
                          typeof(HideTabBar.iOS.CustomRenderer.TabDetailPageRenderer))]

namespace HideTabBar.iOS.CustomRenderer
{
    public class TabDetailPageRenderer : PageRenderer
    {
        public override void ViewWillDisappear(bool animated)
        {
            base.ViewWillDisappear(animated);

            // Show TabBar when main page is displayed
            if (this.NavigationController.ViewControllers.Length == 1)
            {
                (Xamarin.Forms.Application.Current.MainPage as HideableTabbedPage).IsHidden = false;
            }
        }

        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            // Hide TabBar when details are displayed
            if (this.NavigationController.ViewControllers.Length > 1)
            {
                (Xamarin.Forms.Application.Current.MainPage as HideableTabbedPage).IsHidden = true;
            }
        }
    }
}

 

3. Sample usage



    
        
            
                 
            
        
    

using System;
using HideTabBar.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace HideTabBar.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MainPage : HideableTabbedPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}

 

4. Final result

Full source code

Image may be NSFW.
Clik here to view.
Auto Hiding TabBar
Auto Hiding TabBar

Viewing all articles
Browse latest Browse all 3

Trending Articles