Xamarin.Forms Shell — Let’s Customize The Flyout Menu!
So I like to call myself a Mobile Developer, but the truth is that I’m still so new to development that I feel lost from time to time, so when my company decided to task me with building an app from scratch — I was to say the least, a little overwhelmed.
I’ve only been coding for a little over a year, and I had never laid my eyes on Xamarin before March of 2019 — yet that’s the language we decided to write this new app in, and I specifically started looking into Shell because it had a lot of positives, and from what I could see initially there weren’t too many negatives. So I dove in and started fumbling through code samples to try and get my bearings. I put together a few dummy apps before starting to really work on the app that I was tasked with creating. Everything was going great until I got to building out the Flyout Menu and realized that it wasn’t going to serve the design I had been given (gotta love when marketing gets involved in the development process). So there I sat with a concept that Shell couldn’t support out-of-the-box , thus the first challenge of my short career as a developer began: Customizing the Flyout.
Starting from Scratch
Now, let’s be clear: the Flyout Menu in Xamarin Shell is an amazing way to utilize a side panel navigation like you’d get in a Master/Detail page design while incorporating a new navigation schema with the Uri Routing. [Read no navigation page, stack management, etc] but that being said, there is very minimal customization. So what you start with is a menu that looks like this:
Now, don’t get me wrong it looks clean— the icon and clean layout is great for a simple menu of a few items, but my app needed to display up to 47 options (this would be unique to every user based on their account), and they needed to be grouped together in a way that was easy for users to go to the ‘section’ they wanted to first. So I had a decision to make: Start over with Master/Detail or figure out how to customize the menu.
I Chose Customization — This Is What I Did
I started by taking a step back and thinking through how the menu really needed to work. My main needs were group headers, and a clear separation of items and menus within each group. Once I had my plan I set off to figure out how to actually accomplish my design — I looked through what Shell already offers and started experimenting.
In terms of templates, Shell offers a couple things for customizing the layout of what goes into the Flyout Menu, there is a FlyoutHeaderTemplate, ItemTemplate & MenuTemplate. Since I’m focused on the actual clickable elements I looked at the templating for Item and Menu to start (but I’ll look at HeaderTemplate later).
So Shell designates two distinct objects within the Flyout Menu; an Item element and a Menu element — but after looking around for a couple hours, I couldn’t find anything that looked like a way to group the elements therefore I had to create it from scratch.
Since ItemTemplate was built around a DataTemplate, I chose to build a custom class to extend DataTemplateSelector, and this is what it looked like at first:
I created two DataTemplates, one for an Item and one for a Header, and then wrote the OnSelectTemplate method with a null return simply because I wasn’t sure how to determine what was a header versus an item. Yet I was confident that this was likely the best solution to getting groupings of elements like my design called for. Now I just needed to figure out the layouts, the elements and how to link it all up. Simple, right?
Since Shell uses DataTemplates, I needed to create unique layouts for each element, so off I went to create the templates in the ResourceDictionary in Shell.Resources. I made a couple custom styles first to manage traits like FontSize, Margin, TextColor, HorizOptions, etc.. Then I moved onto the DataTemplates. I used simple StackLayouts just for the linear-ness of what I was looking for.
(Note: I’m using Font Icons to replace images in this app. Head over to James Montemagno’s blog to read about how to accomplish this)
So far so good. I have the initial styling set up, and the selector wired to each template, and have the selector determine what to do with each FlyoutItem.
Using Code Behind To Determine FlyoutItem Type For Styling To Work
First off, there is one step that I missed — and it’s easy to over look. I forgot to assign the FlyoutItemSelector that I created to Shell.ItemTemplate. Without linking that up, then all my styling and hard work thus far is useless. To assign the selector, there’s one line of code to add to Shell. In the main construction, you need to declare the following:
With that assigned, let’s head back to the DataTemplateSelector for a second, because that’s where the determination happens. Remember when I left the OnTemplateSelected method to return null? Well, we need to change that to something like this:
So what this statement allows is for me to define the Route attribute for elements in the XAML, and have that attribute be the value that acts as the trigger for the TemplateSelector to pass the right template to the UI. In the XAML I can define Header Groups by adding “Header” into the route and they’ll receive the Header template, while any element that doesn’t start with “Header” will receive the Item template. That completes the linking of the Selector to Shell itself, and the only remaining task is to create the Flyout itself.
Creating the FlyoutItems
Now the tedious work of creating your element hierarchy that will be displayed in the Flyout Menu itself. This can be done through XAML or C#, although creating it in XAML is a static list, meaning they’ll never change based on a user’s credentials. So if your menu options are always going to stay intact, then writing in XAML is the obvious choice, and based on what we’ve done thus far, we simply need to just do something like this:
For a Header Element
With an element that you’ve designated as a header, there are only three attributes to include: Title, FlyoutDisplayOptions & Route. For the Selector to grab it, you need to include your “Header” string at the beginning of the Route attribute, because that’s what the TemplateSelector is basing the return template on.
For an Item Element
With the elements that you want to be non-header elements, you’ll just create them as you would normally with Shell. Your FlyoutItem can have an embedded Tab object, which contains your ShellContent. Adding multiple tabs will give you the TabBar effect for all the pages within the FlyoutItem element.
Once you’ve built all the XAML objects, you’re ready for the final styling and designing for iOS and Android.
Adding A Flyout Header
Now that we have the elements created and all the navigation pages linked, it’s time to wrap up the Flyout Menu, and the last thing we need is the Header, and like I said earlier — there’s a template for that, so this is what I did.
I started by using the fantastic PancakeView from Steven Thewissen as a wrapper for my StackLayout so that it filled the entire bounds of the Header. I used the gradient as a starting point so that I could set the background of the Flyout itself as a static white color. With the gradient ending at a specific color, we can declare that color as my Flyout background which gives us something like this as the final product.
You may be wondering why I only set the PancakeView Gradient on the Header rather than just extending it across the entire Flyout? Well, that’s because the BackgroundColor attribute of Shell allows for only a Color to be passed through and not a complete view. Although I was reading an article last night by Ian Vink, about using ExportRenderers to create a more significant gradient fade across the Shell Flyout — so if you’re really interested in a much deeper gradient fade check out this article.
As you can see, the difference is color may be subtle, but the visual difference between menus, clickable objects and header groupings is something that could really make the flyout serve as a navigation utility for any app with a large collection of menu options. Customizing the Flyout like this is really just for aesthetics since it’s a visual flourish, and you can flourish it alot considering that each type of item in the Flyout can have it’s own template: MenuItem, FlyoutItem and the header object. Ultimately with the TemplateSelector you can really narrow the scope and make different templates for FlyoutItems that you want to have button indicators and others that you want to stay plain. You could make a template that changes colors or has a different border. It’s as flexible as you are which just goes to show how dynamic you can make it.
That’s it. Glad you stuck around to read through what I’ve learned about Xamarin Shell in the last few months. If you’re looking for more Xamarin goodness, head over and read the rest of the articles compiled in the #XamarinUIJuly Challenge here.