Change the font type of a NavigationPage Title in Xamarin Forms

For an upcoming blog post I wanted to use a custom font for the title of my Xamarin Forms NavigationPage. Whether or not it is against the design guidelines is another discussion.

While you can easily set the BarBackgroundColor and the BarTextColor on a NavigationPage, changing the font can’t be done like that.
So like so often, a custom renderer can help you out.

Adding a custom font

iOS

  • Copy your font file (in my case space_age.ttf) to the Resources folder and add it to your project.
  • Check the file properties, set build action to “BundleResource” and Copy to output directory to “Always true”
  • Change your info.plist file and add the UIAppFonts key:
<key>UIAppFonts</key>  
    <array>
        <string>space_age.ttf</string>
    </array>

Android

  • Copy your font file (in my case space_age.ttf) to the Assets folder and add it to your project.
  • Check the file properties, set build action to “AndroidAsset”

The custom control

The PCL control

In your PCL, create a class for your custom NavigationPage

public class SpaceNavigationPage: NavigationPage  
{
    public SpaceNavigationPage(Page root):base(root)
    {
        BarBackgroundColor = Color.DarkBlue;
        BarTextColor = Color.White;
    }
}

The iOS custom renderer

[assembly: ExportRenderer(typeof(SpaceNavigationPage), typeof(SpaceNavigationPageRenderer))]
namespace DevProtocol.Xam.Demos.SpaceNav.iOS.Renderers  
{
    public class SpaceNavigationPageRenderer: NavigationRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null)
            {
                var att = new UITextAttributes();
                att.Font = UIFont.FromName("Space Age", 24);
                UINavigationBar.Appearance.SetTitleTextAttributes(att);
            }
        }
    }
}

The Android custom renderer

Most of the Android examples I found are making use of axml files. In my case I just wanted to write 1 custom renderer that contains the needed code. I find my solution more concise and easy to implement:

[assembly: ExportRenderer(typeof(SpaceNavigationPage), typeof(SpaceNavigationPageRenderer))]
namespace DevProtocol.Xam.Demos.SpaceNav.Droid.Renderers  
{
    public class SpaceNavigationPageRenderer: NavigationPageRenderer
    {
        private Android.Support.V7.Widget.Toolbar toolbar;

        public override void OnViewAdded(Android.Views.View child)
        {
            base.OnViewAdded(child);
            if (child.GetType() == typeof(Android.Support.V7.Widget.Toolbar))
            {
                toolbar = (Android.Support.V7.Widget.Toolbar)child;
                toolbar.ChildViewAdded += Toolbar_ChildViewAdded;
            }
        }

        private void Toolbar_ChildViewAdded(object sender, ChildViewAddedEventArgs e)
        {
            var view = e.Child.GetType();
            if(e.Child.GetType() == typeof(Android.Widget.TextView))
            {
                var textView = (Android.Widget.TextView)e.Child;
                var spaceFont = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, "space_age.ttf");
                textView.Typeface = spaceFont;
                toolbar.ChildViewAdded -= Toolbar_ChildViewAdded;
            }
        }
    }
}

References

Download

Download the code from my GitHub