Press "Enter" to skip to content

Navigation Bar Customization in Xamarin Forms

When dealing with the navigation bar in Xamarin Forms, is pretty limited what we can do related to customization. So when this is needed there are generally two approaches people follow:

  1. Hide the Xamarin Forms navigation bar and implementing a custom one using any forms layout. The problem with this approach might be handling the glitches caused by navigation transitions especially on Android when using the forms navigation bar on some pages and in other’s not.
  2. Implement customization on each platform by using custom renderers.

In this article, we are going to focus on the second one.

Xamarin Forms

The first thing to do is to create a CustomNavigationPage class that extends from the NavigationPage class and add some attached properties to achieve extra customization.

  • TitlePositionProperty – This property will get/set the position for our title (Start, Center or End).
  • TitleBackgroundProperty – Gets/Sets the background for the title view.
  • TitleFontProperty – Gets/Sets the font for the title text.
  • SubtitleFontProperty – Gets/Sets the font for the subtitle text.
  • TitlePaddingProperty – Gets/Sets the padding for the title view.
  • TitleMarginProperty – Gets/Sets the margin for the title view.
  • TitleBorderCornerRadiusProperty – Gets/Sets the border radius for the title view.
  • TitleBorderColorProperty – Gets/Sets the border color for the title view.
  • TitleFillColorProperty – Gets/Sets the fill color for the title view.
  • TitleBorderWidthProperty – Gets/Sets the border width for the title view.
  • BarBackgroundProperty – Gets/Sets the background for the navigation bar.
  • GradientColorsProperty – Gets/Sets the gradient colors background for the navigation bar.
  • GradientDirectionProperty – Gets/Sets the direction for the bar background gradient.
  • HasShadowProperty – Gets/Sets the shadow for the bottom of the bar.
  • BarBackgroundOpacityProperty – Gets/Sets the opacity for the bar.

Also, let’s create a CustomPage to support some flexibility by having a subtitle and formatted text support. To provide this let’s add the following properties:

  • Subtitle – Property to set a plain subtitle text
  • FormattedTitle – Will provide us the flexibility to format individually every part of our title text.
  • FormattedSubtitle – Will provide us the flexibility to format individually every part of our subtitle text.

For FormattedTitle & FormattedSubtitle will use type FormattedString (This will allow us to use spans to create our formatted text string).

Android

On Android we got the AppCompat Toolbar to apply our customization. We should be able to do this by implementing a custom NavigationPageRenderer.

NOTE: Make sure to add [assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(CustomNavigationPageRenderer))]  to your custom renderer.

The next step will be to create a new class called CustomNavigationPageRenderer and extends from NavigationPageRenderer. After that, we are going to overwrite the method OnViewAdded to detect when Toolbar is added.

We created a FrameLayout with a LinearLayout inside that contains a title and subtitle TextView.The linear layout represents the title view as a whole (title and subtitle).

We subscribe to ChildViewAdded toolbar event to listen when Xamarin Forms adds default toolbar child text view so we can hide it and show just ours with the desired customization for the current page. Also to the page PropertyChanged event to listen to attached property changes.

By overriding SetupPageTransition we can set up the correct customization when a page is popped or pushed. When pushed we first stop listening to the previous page PropertyChanged event and start listening to the new pushed page PropertyChanged event. Finally, apply the current proper customization for the navigated page. When popped we stop listening to the current page PropertyChanged event, listen to the previous page PropertyChanged event and restore previous page customization.

Here how we achieve our customization based on the attached properties:

Title Position

For positioning our title layout we set the gravity of all our views to the specified value set on CustomNavigationPage.GetTitlePosition for the current page shown.

Title Background

We set the title layout name by looking for the resource identifier for the name specified in CustomNavigationPage.GetTitleBackground for the current page.

Title & Subtitle Font

Xamarin Forms Font has an Android extension ToTypeface() that gives you the native typeface equivalent to the font we set on Forms.

Formatted Text

For setting formatted string text, Forms has a pretty handy extension method ToAttributed() that returns the formatted text equivalent for Android native platform.

Title Padding and Margin

We set the padding to our title view layout and apply the margin to the layout parameters of this layout.

Title Fill & Border Color, Corner Radius and Width

We use a method called CreateShape to create a GradientDrawable that allow us to set the title fill, border color, radius and width by setting this drawable on the title view layout background.

Bar Background, Opacity, Gradient Colors and Direction

For the toolbar background, we set the background to the value CustomNavigationPage.GetBarBackground which is the name of the drawable to set as background. The opacity (0-1) is set by using CustomNavigationPage.GetBarBackgroundOpacity which is a value from  0 to 1, so we multiply by 255 to set the alpha of the toobar background. In the case of the bar background gradient we use a gradient drawable to set the gradient colors and direction based on CustomNavigationPage.GetGradientColors and CustomNavigationPage.GetGradientDirection values.


Bar Shadow

To set the shadow we find the FrameLayout inside the activity Window DecorView to set a GradientDrawable with the shadow colors. We set as well the right toolbar elevation to achieve the shadow effect

iOS

On iOS we got the UINavigationBar we can apply our customization to specific pages by using a custom PageRenderer. The reason we didn’t use a NavigationPageRenderer as on Android is because of the lifecycle of iOS view controllers, we need to do the customization after view controller is loaded and will appear on the screen. Doing it with a navigation page renderer might be too late or too early since we don’t have feedback on the view controller events, so we won’t have the behavior we expect.

NOTE: Make sure to add [assembly: ExportRenderer(typeof(ContentPage), typeof(CustomPageRenderer))]  to your Custom Renderer. 

As you can see here we are going to apply the renderer to all the pages in the application, if you want to apply it to just one page make sure to create a new ContentPage class in your Forms Project and use that type in the ExportRenderer typeof.

The next step will be to create a new class called CustomPageRenderer and extends from PageRenderer. After that, we are going to override method ViewDidLoad to create our custom navigation bar view there and also start listening to PropertyChanged events on this page so that we can adapt customization when any property changes. Which will be a container UIView with another UIView to handle margins inside and then our title UIView which contains two UILabels one for the title and other for the subtitle.

Then we override ViewWillAppear to set our navigation bar customization, also we need to consider doing this if device is rotated or layout changes occur a good ViewDidLayoutSubviews. We set the title position as well on each on these methods.

SetupNavBar is the method that does the customization magic on iOS, since is the responsible to configure all customization that was set in CustomNavigationPage attached properties and also sets our custom title view on ParentViewController.NavigationItem.TitleView.

Title Position, Padding and Margin

To set the title position, padding and margin we basically calculate the correct Frame for the parameters set considering the position, padding, margin and text size as well.


Title & Subtitle Font

Xamarin Forms Font has an iOS extension ToUIFont() that gives you the native font equivalent to the one we set on Forms. For setting formatted string text, Forms has a pretty handy extension method ToAttributed() available on a FormattedString type that returns the formatted text equivalent for iOS native platform.

Bar Background, Opacity, Gradient Colors and Direction

We set the opacity by setting the NavigationController.NavigationBar.Alpha to our CustomNavigationPage.GetBarBackgroundOpacity. Also, we if CustomNavigationPage.GetBarBackground is set we load the UImage with this name to set it as the NavigationBar background.

We create the gradient by using CreateGradientBackground method that basically creates an UIImage based on a CAGradientLayer which properties are set based on the values of  CustomNavigationPage.GetGradientColors and CustomNavigationPage.GetGradientDirection attached properties. Then set this created image as the NavigationBar background.


Bar Shadow

We set the shadow if CustomNavigationPage.GetHasShadow is true by setting NavigationController.NavigationBar layer properties: ShadowColor, ShadowOffset, ShadowOpacity.

Here some examples of how to use on Page:

//Sets the title position to end

CustomNavigationPage.SetTitlePosition(this, CustomNavigationPage.TitleAlignment.End);

//Sets shadow for bar bottom

CustomNavigationPage.SetHasShadow(this,true);

//Gets if has shadow or not

bool hasShadow = CustomNavigationPage.GetHasShadow(this);

//Sets the title text font to Micro
CustomNavigationPage.SetTitleFont(this, Font.SystemFontOfSize(NamedSize.Micro));

If we want to have a subtitle just make sure your page inherits from CustomPage.

You can check the full source code here:

https://github.com/CrossGeeks/CustomNavigationBarSample

References:

https://xamgirl.com/navigation-bar-with-shadow-in-xamarin-forms/

https://github.com/jsuarezruiz/xamarin-forms-customnavigationpage

https://blog.wilsonvargas.com/personalizando-un-navigationbar/

https://www.devprotocol.com/change-the-font-type-of-a-navigationpage-title-in-xamarin-forms/

 

Happy customization!

17 Comments

  1. Theodorus Theodorus

    I already tried your code and im tried to make the logo on navbar to center there is no error message but the logo is not showing, can you give me suggestion ? i already write this in my code
    CustomNavigationPage.SetTitleBackground( this, “ic_myvalue”);
    CustomNavigationPage.SetTitlePosition(this , CustomNavigationPage.TitleAlignment.Center);
    but still the logo not showing

  2. Good article and control but there are a few issues around alignment. On IOS titles appear off centre. This does not happen in a consistent way. On an iPad tiles appear to the right of centre and on an iPhone to the left of centre. I’m able to compensate by adding padding (spaces) but I’m not sure if this will work across screen sizes. I hope this helps with making this control even better. Best Regards

  3. Pacodoso Pacodoso

    Hi Rendy!
    Thanks for sharing.
    Regarding your experience, do you think that we could display a NavigationBar “behind” an Image that is contained in a Grid on the Page? By playing with it’s opacity?
    This would be easyier to explain through an image 😉

  4. Rendy Rendy

    Yes might be better if you post a brief gif or video of what you would like to achieve.

  5. Pacodoso Pacodoso

    The menu is the Master part of a MasterDetailPage, that is always visible.
    The right part is the Detail part of a MasterDetailPage, that contains the NavigationPage.

    • Rendy Rendy

      Did you try applying a Transparent background color to the Navigation Bar?

  6. Barbe Barbe

    Hi there and thank you for your awesome work !

    I have a question. With your code is it possible to set the same title text or icon on every page in a way it will not slide nor move or blink when the user change page ?

    Thank you !

    • Rendy Rendy

      Yes, should be a smooth transition.

  7. Matthew Morton Matthew Morton

    Dude, THANK YOU SO MUCH FOR THIS!!!!!!

    I’m a professional developer, but I write C++/Python Backend CLI applications, so when it comes to UI stuff I’m worse off than Shamu in the desert lol But I had been struggling with centering the navigation bar text (probably more than I should have).

    But yours is honestly the first solution of many I tried that everything worked as perfectly as you can realistically hope in this field lol. There was a few minor tweaks, but that was entirely due to my own code.

    I just wanted to say thank you because your solution not only solved the one part I needed, it extends the basic functionality VERY extensively, so this is going to be even more awesome now when I’m finally done!

    Thanks again!

    • Rendy Rendy

      Glad that it was helpful 🙂

  8. Steven Lawrence Steven Lawrence

    I got as far as implementing the Android CustomNavigationPageRenderer, why post each override individually? I’ve copied the code but where are the private fields being declared that the overrides reference? Also missing ‘LastPage_PropertyChanged’ and ‘SetupToolbarCustomization’ which are both referenced in the code in this post.

  9. Josué Mora González Josué Mora González

    Thanks for your post, I tried it but not success, on CustomPage class all values that begin with “FormattedTitle” throw errors.

  10. Jo Jo

    Hi there,
    Fantastic articles on xamarin.
    Came across this article and download your example that works.

    I am using a masterdetail page using prism and even though it hits the code it never changes the background color of the navigation bar. Any ideas? Thanks

  11. Mark Mark

    Hi there,
    Fantastic articles on xamarin.
    Came across this article and download your example that works.

    I am using a masterdetail page using prism and even though it hits the code it never changes the background color of the navigation bar. Any ideas? Thanks

  12. AMan AMan

    Great solution help me save my day

  13. Dattatray Zende Dattatray Zende

    I was looking for back button customization. I noted you have mentioned this as future work. Is this available now? I did not see it on the Github though,
    Thanks for a great post.

Comments are closed.