Wanna build some awesome themes into your Xamarin.Forms Shell project? Change the App themes during the run time dynamically? Save the theme properties in User Settings? Then you’re at the right place! 😉
Themes in Xamarin.Forms Apps…
Given Xamarin.Forms is such an incredible cross platform mobile framework, it provides a lot of awesome features out of the box, but unfortunately it doesn’t straight away provide App Theme feature in your face. 😛 but…
It’s got all the bells and whistles you need to implement an awesome App Theme set up with ease, in combination of awesome Dynamic Binding, Static Binding and Style Properties giving you full control of how to handle implementing Themed Styles into your app. You just gotta put together all those bits and you can easily build App Themes functionality into the app.
This is actually quite powerful given the cross platform nature of Xamarin.Forms! Now there are plenty of documentation, articles and sample demos regarding this, so I’m not going to be repeating on that topic, but if you’re interested try out this office doc article from Microsoft: Theming a Xamarin.Forms Application Now that gives a very good step by step explanation on the topic for anyone to easily get started, but anyhow focusing back on this article…
Enters, Xamarin.Forms Shell Apps…
Then enters the recently introduced Xamarin.Forms Shell, a new paradigm of Xamarin.Forms App development. Now when I got started with this new awesomeness, I couldn’t find any direct articles or samples on how to implement App Themes in a Xamarin.Forms Shell projects.
So I had to figure it out myself, and that’s why I thought of sharing my experience with you guys. Now now, don’t get me wrong, since we’re still in the same context of Xamarin.Forms, the App Theming strategy is still the same as the official doc I shared about, but I may have found a better way and a bit of improvements on top of that. 😉
So let’s get started… Stunning app Themes in Xamarin.Forms Shell projects!
How to? in a nutshell!
Basically in a nutshell we’re going to define a set of Themes with Color Properties inside them that holds Color values unique to each Theme. Then we will build all a complete collection of Styles targeting all the components in our app such as Button, Labels and so on. Now in this case we need to stick to Dynamic Binding since we’re going to be switching between Themes during run time, so use of Xamarin.Forms DynamicResource binding all the way ah! 😉
Next we make sure all our UI elements are bounded to those Styles that we created before and still making sure to stick to Dynamic Binding. Now that we have established the binding chain from Theme Properties to Styles to UI Elements, we need to set up the default Theme to load in the ApplicationResources XAML node.
Once all that’s set up we shall be implementing a simple mechanism to save the User’s App Theme preferences, with features such as Saving and Reloading those preferences on demand.
And that’s it! 😀
Here’s a little sneaky peaky demo magic on Android and iOS.. 😉
If you’d like a sneak peak into the code before I get into the code details, you can find the whole demo project here in my github repo: https://github.com/UdaraAlwis/XFShellAdvThemeing
So in my demo code, I have used the default out of the box Xamarin.Forms Shell project template you get in Visual Studio 2019 latest update, so that you can easily familiarize yourself with the code and adopt the same implementation in your own code.
Set up of the project!
Let’s get started with the set up of the Project, but first should take a look into the structure we’re going to be implementing, where we need to first focus on the following aspects.
- List of Themes for the App
- List of properties in a given Theme
- Styles built using the properties of Themes
- Helper extension to change App Theme
- Saving the User’s App Theme preferences
Now keeping those main aspects in mine, I’m going to assume that you have already set up your basic Xamarin.Forms Shell app project. I’m going to name my little demo as XFShellAdvThemeing, denoting Xamarin.Forms Shell Advanced Theme-ing! 😉
Alright there goes our Xamarin.Forms Shell App project, with strong base of MVVM baked in! You may have noticed I have added “Themes” folder, which will hold the App Themes that we’re going to create. And then a “Helpers” which will hold a simple extension method that we’re going to built for switching the App Theme selection by the user during run time.
Building the App Themes…
Time to define the App Themes, so first of all we need to be specific about what properties we are going to be using to each Theme, be it colors, fonts, images and so on, you need to be specific, and make sure all the Theme definitions follow the exact same format.
on github: /XFShellAdvThemeing/Models/Theme.cs
Here I have defined the list of Themes that I’m going to include in my App, and as for having the type of Enum, is for to be used later in the code to populate the data to the User. So make sure to add a record here every time you add a new Theme to your app.
This step is very crucial because you shouldn’t neglect this and try to change the app theme properties half way into the app development. If you’re working with a team,
…you need to define with the team designers together how the Themes of the app should behave, and what elements should be controlled over them.
For this demo I’m going to define the following list of properties inside each Theme.
- Main Colors:
- Primary Color
- Accent Color
- Secondary Color
- Page Colors:
- Page Background Color
- Navigation Bar Color
- Text Colors
- Primary Text Color
- Secondary Text Color
- Tertiary Text Color
As you can see I have taken into consideration of having 3 set of main Colors, and as a back up since I’m going to be using native Navigation bar, a property to control its colors and the Page background as they render next to each other. Then finally the Colors for the Text inside the app.
Its very crucial you develop this kind of design centric thinking when you’re developing any mobile app…
So let’s create our beautiful little XAML snippets inside the Themes folder that are going to hold all the properties of each App Theme.
Just simply add a XAML page into the Themes folder and rename the parent node to ResourceDictionary of type and update the same in the code behind as well.
on github: /XFShellAdvThemeing/Themes/DarkTheme.xaml
There my first theme, LightTheme which holds the color values I need to customize in my app for Theme-ing! 😉 Feel free to add as many themes as you like following the same structure.
Defining the Styles…
Now these bits are the middle man between your UI elements and the Theme definitions. As I explained before we are going to create Styles targeting all the types of UI Elements that we’re using in the app, so that we can “Style” them with those! 😉 get it!? lol
on github: /XFShellAdvThemeing/App.xaml
You can define these Styles as a Global App resources or in Page levels as you wish, but I have added them into my App.xaml for this demo, such as Styles targeting Buttons, Labels, etc.
As you can see we are using DynamicResource binding to hold on to the Theme property values, so that we can update our Style property values dynamically in run time.
Now you might wonder why I have referenced Themes/LightTheme.xaml in the global Resource Dictionary, well… that is to set the default theme as the Light App Theme that I just defined above. You can keep it as it is or watch me switch the App Theme dynamically during run time below… 😉
You also need to directly reference your Shell bound UI Elements using the Theme properties we defined earlier. Here I have added to to the same App.xaml global scope instead of keeping it in the AppShell.xaml scope, just for organizing the styles in one place.
Switching App Theme Dynamically…
Now of course we need to allow our App to be able to switch the Theme dynamically during run time according to User’s choice or some configuration built in. We can easily do this in Xamarin.Forms, using MergedDictionaries property by removing the existing Theme in memory Resources and switching to our choice of Theme Resources.
I have created a simple Helper extension, with the method SetAppTheme() which accepts the type of Them Enum value you need to use and returns the boolean result.
on github: /XFShellAdvThemeing/Helpers/ThemeHelper.cs
Like I said before this is where out little Helper extension comes into play, so just add this little snippet into your Helpers folder.
Based on the Theme Enum identifier value, we will be instantiating the Theme object, assigning it to the Resources in memory as you see above.
Now that’s all cool and stuff, but how about persisting this preferred theme selection?
Saving to User Preferences!
This can easily be done with the help of Xamarin.Essentials, which allows us to save Application context key values pairs using the Preferences API. Now I believe in Visual Studio when you create a new Xamarin.Forms Shell project by default it comes pre-installed with Xamarin.Essentials, otherwise make sure to add it to your project from nuget.
We are going to save the Selected App Theme settings with the key name “CurrentAppTheme” as below.
And make sure to load it back to the app during the App’s launch event and call up on our little magic extension ThemeHelper.SetAppTheme() as shown here..
on github: /XFShellAdvThemeing/App.xaml.cs
You need to call that in the App() constructor invoke, so that we can load the saved App Theme settings instead of loading the default one that we set up in App.xaml resources.
Bingo! nice little App Theme Selection Page to our Xamarin.Forms Shell App! 🙂
Time for some action!
Here it is side by side iOS and Android,
Themes with more than Colors?
Now our App Themes aren’t always going to be as simple as a bunch of Color properties right?! It could even contain Fonts, Text Sizes, Images, Icons and so on. But if you’re wondering if that’s even possible in Xamarin.Forms, yes absolutely you can!
It’s basically no different than defining a Color property in your Theme.xaml file, just add the XAML node to the file and you’re good to go!
Make sure to give it a Key name value though, and reference it in your Styles as usual where applicable.
You can follow the same pattern for any kind of Theme property you want to add and basically you’re good to go! 😉
Github Repo: github.com/UdaraAlwis/XFShellAdvThemeing
Any property that you can reference usually from your XAML, you can easily include them in your App Theme and link the binding through Styles to your UI elements straight away.
Here are some tips and tricks that might come in handy for you, during the whole shabang of “Theme-ing” your Xamarin.Forms Shell app projects.
More Unification! Less Repetition!
Make sure to avoid adding repetitive theme properties into the Theme XAML definitions, by unifying the Colors, Fonts, Icons you use in your app. As an example if you define a Text Color property in your Theme, make sure to use that only for Text Coloring Elements and Styles, try not to use them for other aspects.
So you can easily manage those properties in future and they’d be easy to understand for anyone to extend the properties. This is quite crucial when you maintain massive App Projects, and it wouldn’t affect the capability to grow the App code altogether.
Stubborn Native Elements?! Yikes!
Now as you probably know or don’t Xamarin.Forms doesn’t let you change the color values of your App’s few very native elements during run time. Such as,
– iOS/Android System Status Bar Colors
– Android UI Elements that contains horizontal bar such as Entry, Picker, etc. (Unless you’re using Xamarin.Forms Material Visual)
They require native Android/iOS level access to change during run time. So you need to have Custom Renderers or Native Bound Services that can be communicated through Xamarin.Forms layer during run time. Well that’s a blog post for another time! 😉
So here’s how it could be easily solved as you can see below,
My suggestion would be to maintain values of those UI elements as compatible as possible that could be matched with the Theme Colors you currently use. Such as light Gray, White or Black mostly.
You can easily set them up from Resources/values/styles.xml in your Android project.
And on iOS project’s Info.plist configuration.
And that’s pretty much it!
Share the love! 😀 Cheers!