Enable and control iOS 11 Large Titles in Xamarin.Forms

With iOS 11, Apple introduced a bunch of new design elements to its mobile platform. One of them arelarger titles, that sit in the Navigation Bar and can be scrolled away when more space is needed. Large Titles can be enabled with a few lines of code in iOS. To use them with Xamarin.Forms, we need to extend the framework on our own, as the new titles are not officially supported yet.

iOS 11 Large Titles Screenshots

UPDATE

With Xamarin.Forms 2.5, a platform-specific for Large Titles has been added. Read this post for further details.

// Call this on your NavigationPage to activate Large Titles
NavigationPage.On<iOS>().SetPrefersLargeTitles(true);

// Use this on single pages to opt-out 
On<iOS>().SetLargeTitleDisplay(LargeTitleDisplayMode.Never);

Enable Large Titles

To add support for Large Titles in Xamarin.Forms all we need to do is overriding the existing NavigationRenderer and enable Large Titles application-wide. Simply add this Renderer to your iOS project and they will be shown everywhere.

[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationRenderer))] 
namespace LargeTitles.Forms.iOS.CustomRenderers { 
    public class CustomNavigationRenderer : NavigationRenderer 
    { 
        protected override void OnElementChanged(VisualElementChangedEventArgs e) 
        { 
            base.OnElementChanged(e); 
            
            // Enables iOS 11 new Large Titles system-wide
            if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { 
                // Enable Large Titles
                NavigationBar.PrefersLargeTitles = true; 
                
                // Adopt same TextAttributes as for normal titles, beacuse Xamarin.Forms NavigationPage 
                // does not have a dedicated property for this yet 
                UINavigationBar.Appearance.LargeTitleTextAttributes = new UIStringAttributes 
                { 
                    ForegroundColor = (Element as NavigationPage)?.BarTextColor.ToUIColor() 
                }; 
            }
        }
    }
}

Control when to display Large Titles

Being in control of when to display the new titles or not is a nice feature as they totally do not make sense on every page and this gives us more flexibility on when and where to use them.

Unfortunately, Xamarin.Forms is struggling with the new Large Titles and bottom offsets sometimes, especially when combined with aTabbedPage. So we need a way to switch them off manually for each page.

Extend Content Page

For this, create a new type of ContentPage in your Xamarin.Forms project, that is aware of Large Titles and offers a property to switch them on and off manually.

namespace LargeTitles.Forms.Controls 
{
    public class ModernContentPage : ContentPage 
    { 
        /// <summary> 
        /// Property for iOS 11 new Large Titles 
        /// </summary> 
        /// <value><c>true</c> if should have large title; otherwise, <c>false</c>.</value> 
        public bool HasLargeTitle { get; set; } 
    }
}

Every page, that should be able to switch off large titles (we enable them by default in the Custom Renderer above), must now be type of our newly created page. This has to be declared in XAML

<controls:ModernContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:controls="clr-namespace:LargeTitles.Forms.Controls;assembly=LargeTitles.Forms" 
    x:Class="LargeTitles.Forms.Pages.TestPage" 
    Title="Hello World"
    HasLargeTitle="false">
    <!-- ... -->
</controls:ModernContentPage>

… and the code-behind as well.

public partial class TestPage : ModernContentPage

Add a Custom Renderer

All we need now is a Custom Renderer for the new page, that respects the HasLargeTitle property and sets the in iOS 11 introduced LargeTitleDisplayMode property accordingly. Create a new Custom Renderer in the iOS project and expose it.

[assembly: ExportRenderer(typeof(ModernContentPage), typeof(ModernContentPageRenderer))] 
namespace LargeTitles.Forms.iOS.CustomRenderers 
{ 
    public class ModernContentPageRenderer : PageRenderer 
    { 
        public override void ViewWillAppear(bool animated) 
        { 
            base.ViewWillAppear(animated); 
            
            // Check, if iOS 11 Large Title shall be displayed or not
            if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) 
            { 
                if ((Element as ModernContentPage)?.HasLargeTitle == true)
                    NavigationController.TopViewController.NavigationItem.LargeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Always; 
                else
                    NavigationController.TopViewController.NavigationItem.LargeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Never; 
            }
        }
    } 
}

Et voilà! With 12 lines of code, Xamarin.Forms becomes capable of using the new Large Titles and looks nice and modern for Apple’s new version of iOS.