Xamarin.Tip – iOS Material Design Navigation Bar

To keep the Material Design coming to iOS, let’s look at making our NavigationBar more material.

Here’s what a “standard” UINavigationBar looks like on iOS:

Screen Shot 2017-05-16 at 12.25.17 PM

And here is what a Material Design Toolbar looks like on Android:
layout_structure_appbar_structure4

The goal here is to get something more similar to the Android Material Design look. The most notable differences are the drop shadow created by the toolbar onto the rest of the view as well as the distinct back button and other icons.

So, if you’re using Xamarin.Forms, you’ll need to create a custom renderer to get this job done. Let’s take a look at that:

MaterialNavigationRenderer.cs


[assembly: ExportRenderer(typeof(NavigationPage), typeof(MaterialNavigationRenderer))]
namespace YOUR_IOS_NAMESPACE
{
    ///
<summary>
    /// Custom renderer creating a material design navigation bar
    /// </summary>

    public class MaterialNavigationRenderer : NavigationRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            // Create the material drop shadow
            NavigationBar.Layer.ShadowColor = UIColor.Black.CGColor;
            NavigationBar.Layer.ShadowOffset = new CGSize(0, 0);
            NavigationBar.Layer.ShadowRadius = 3;
            NavigationBar.Layer.ShadowOpacity = 1;

            // Create the back arrow icon image
            var arrowImage = UIImage.FromBundle("Icons/ic_arrow_back_white.png");
            NavigationBar.BackIndicatorImage = arrowImage;
            NavigationBar.BackIndicatorTransitionMaskImage = arrowImage;

            // Set the back button title to empty since Material Design doesn't use it.
            if (NavigationItem?.BackBarButtonItem != null)
                NavigationItem.BackBarButtonItem.Title = " ";
            if (NavigationBar.BackItem != null)
            {
                NavigationBar.BackItem.Title = " ";
                NavigationBar.BackItem.BackBarButtonItem.Image = arrowImage;
            }
        }
    }
}

This will override our Renderer for all of our instances of a NavigationPage. To breakdown what is being done here, the renderer is initializing the native UINavigationBar, then updating the Layer of the UINavigationBar to create a drop shadow. After that, we instantiate the back arrow icon to replace the default iOS one. Lastly, we set the back button title to empty so that it doesn’t show up next to our new back button image.

The back button icon is taken from the official Material Design Icons from Google found here: https://material.io/icons/

The last thing we need to do is update our toolbar icon to fit the Material standards (thicker and bolder). To do this, we go back to the icons linked above and download the new check icon we want and substitute the ToolbarItem we have in our XAML.

Now we can see the results of our custom renderer and updated icon with our more Material Design looking toolbar:

Screen Shot 2017-05-16 at 12.31.37 PM

 

Next Steps

Want to take it further? Try updating your custom renderer to move the Title text alignment to the left and use the Roboto font! Check out this blog post on how to bring Roboto to your iOS fonts: https://alexdunn.org/2017/05/03/xamarin-tips-bringing-material-design-fonts-to-ios/.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

Xamarin.Tips – Bringing Material Design Fonts to iOS

We might as well continue this trend of bringing Material Design to our iOS apps. Be sure to check out my previous posts on Material Frames in Xamarin.Forms iOS and Material Design Buttons in iOS (Native and Xamarin.Forms). Let’s talk about fonts now.

Material Design states that the preferred fonts to use are Roboto and Noto: https://material.io/guidelines/style/typography.html. These fonts ship in Android natively from Android 5.0+ (API Level 2.1) or when using the Android App Compat packages. However, these are not part of the OS in iOS, so if we want to fit a more Material Design standard, we need to bring those into our own apps.

Downloading and Installing the Fonts

First things first, we need to download both of these fonts from Google’s open web fonts.

  1. Roboto: https://fonts.google.com/specimen/Roboto
  2. Noto: https://fonts.google.com/specimen/Noto+Sans

You’ll need to make sure you don’t just download the Regular font files for both of these, but also each of the weights you’ll want to use in your app.

Now that you have all your .ttf files, you’ll need to bring them into your project. Place them in a folder at iOS Project > Resources > Font. Also make sure that each of their BuildActions are set to BundleResources. Do this by going to the Properties of each file and use the Build Action dropdown.
RobotoFontsInVS.PNG

The last step in getting them property installed is to update your Info.plist file to include the fonts. After this step, we’ll be able to start using it.

In Visual Studio, open your Info.plist file with the Generic PList Editor. When you do that, it should look something like this:
infoplistdefault

Scroll down to the bottom and add a new Property. You can use the dropdown to find it, or type it out yourself, but it needs to be Fonts provided by application. Set the type of this new item to Array, then start adding subitems for each of the fonts. For each font, you will need to set the type to String and the value to the path to your font from the Resources folder. So in our case, that will be something like Fonts/Roboto-Black.ttf.

Do this for each of your font files, and it should looks something like this:

infoplistfonts

Now we have our fonts installed into our iOS application, we can start using them!

Using the Font in Xamarin.iOS Native

Now that our application is aware of our font, we can apply it to any UILabel we instantiate in our code:

ExampleViewController.cs

var label = new UILabel(new RectangleF(0,0, width, height /2));
label .Text = "This is a label using Roboto";
label .Font = UIFont.FromName("Roboto-Regular", 20f);
this.Add(label);

Alternatively, we can use the Appearance APIs to apply it to all of our UILabels across our app:

AppDelegate.cs

public class AppDelegate : UIApplicationDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        ...

        UILabel.Appearance.Font = UIFont.FromName("Roboto-Regular", 20f);
        ...
        return true;
    }
}

Using the Font in Xamarin.Forms iOS

Of course, we also might need to use this font in Xamarin.Forms! Just like in native iOS, we need to apply our font, by name to any given label we want, or we can use Styles to apply it everywhere.

ExamplePage.xaml

<ContentPage ...>
    <Label FontFamily="Roboto-Regular" FontSize="20" Text="Xamarin.Forms Roboto on iOS"/>
</ContentPage>

or:

App.xaml

<Application ...>
    <Application.Resources>
        <ResourceDictionary>
<Style TargetType="Label">
                <Setter Property="FontFamily" Value="Roboto-Regular"/>
                ...
            </Style>

        </ResourceDictionary>
    </Application.Resources>
</Application>

Results

Now we have our nicer looking fonts from Material Design applied to our iOS apps. Look at this comparison of some default iOS Frames and Fonts versus our new Materialized look and feel:

Old (Defaults)
iOSDefaultFrameAndLabel

New (Custom Frame and Roboto-Regular Font)
iOSMaterialFrameAndLabel

Are there any other controls you’d like to see Materialized on iOS? Let me know in the comments!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.