Introduction
Recently, for one of our customers, we have started building a mobile application using Xamarin Forms to support both iOS and Android Devices. One of the design aspects which we need to consider is theming the app with different color scheme.
We have the following design goals for theming:
All the UI elements should support theming by changing the theme setting on the fly.
Since we had the developers who came from web technology and they are new to Xamarin Forms, the theming should be simple to implement and consistent across the technology.
XAML styles should be used as compared to Cascade Style Sheet (CSS) as CSS is not mature yet in Xamarin Forms.
This article will assume that you have basic knowledge of C#, XAML Styles and Xamarin Forms and shows how to implement theming using simple styles.
Pre-requisites
You will need the latest version of Visual Studio 2017 with Xamarin workloads and emulators installed.
Step 1 – Create a New Xamarin Forms Project
Let's start creating a new Xamarin Forms project using Visual Studio 2017 and choose File-->New-->Project.
In the New Project windows, Choose Cross-Platform-->Mobil App (Xamarin Forms) as shown below:
Enter the project name as Theming Demo and Click OK, the below option dialog will be displayed:
In the above screen, select Blank Project and click OK, the below project will be created.
Select the emulator and run the project, you should be able to see the Main Page with welcome text as below:
Step 2 – Create XAML Styles
In the shared project, create a new folder called “Themes” and add a new XAML style called “Default.xaml” as shown below:
Once the file is added, open the Default.xaml.cs file and replace the “ContentPage
” with “ResourceDictionary
” as shown below:
using Xamarin.Forms;
namespace ThemingDemo.Themes
{
public partial class Default: ResourceDictionary
{
public Default ()
{
InitializeComponent ();
}
}
}
Open the Default.xaml file and replace the entire content with below styles:
="1.0"="UTF-8"
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.Themes.Default">
<Style TargetType="Label" BaseResourceKey="BodyStyle">
<Setter Property="HorizontalOptions" Value="StartAndExpand" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#AF3800" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium" />
</Style>
<Style TargetType="Switch">
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BackgroundColor" Value="White" />
</Style>
<Style x:Key="MainStackLayout" TargetType="StackLayout" >
<Setter Property="Padding">
<Setter.Value>
<OnPlatform x:TypeArguments="Thickness" Android="8, 8, 8, 8" iOS="10, 10, 10, 10"/>
</Setter.Value>
</Setter>
<Setter Property="VerticalOptions" Value="StartAndExpand" />
<Setter Property="Spacing" Value="5" />
</Style>
<Style TargetType="Label" x:Key="LabelPageHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Label" BaseResourceKey="SubtitleStyle" x:Key="LabelSubHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Button" x:Key="ButtonSecondary">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#aa2029" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium"/>
</Style>
</ResourceDictionary>
Note that, in the above file, we have created few Implicit Styles and few Explicit Styles using XAML. You can find detailed information on Styling Xamarin Forms Apps using XAML Styles here.
We would like to give two different themes to our application. So, let us create a new XAML style called “Pink.xaml”. We have created this style by just copying the Default.xaml and renamed it to “Pink.xaml”. After that, we have changed only color scheme to Pink
color.
The modified content of “Pink.xaml” is shown below:
="1.0"="UTF-8"
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.Themes.Pink">
<Style TargetType="Label" BaseResourceKey="BodyStyle">
<Setter Property="HorizontalOptions" Value="StartAndExpand" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#FF1493" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium" />
</Style>
<Style TargetType="Switch">
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BackgroundColor" Value="White" />
</Style>
<Style x:Key="MainStackLayout" TargetType="StackLayout" >
<Setter Property="Padding">
<Setter.Value>
<OnPlatform x:TypeArguments="Thickness" Android="8, 8, 8, 8" iOS="10, 10, 10, 10"/>
</Setter.Value>
</Setter>
<Setter Property="VerticalOptions" Value="StartAndExpand" />
<Setter Property="Spacing" Value="5" />
</Style>
<Style TargetType="Label" BaseResourceKey="TitleStyle" x:Key="LabelPageHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Label" BaseResourceKey="SubtitleStyle" x:Key="LabelSubHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Button" x:Key="ButtonSecondary">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#e24fd1" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium"/>
</Style>
</ResourceDictionary>
Now the Themes directory looks like below:
Step 3 – Create Theme Manager Helper
Create a new helper class called ThemeManager
and add a public
method ChangeTheme
with signature as below:
using System;
using Xamarin.Forms;
namespace ThemingDemo.Themes
{
public class ThemeManager
{
public static void ChangeTheme(string themeName)
{
Application.Current.Resources.Clear();
Application.Current.Resources.MergedDictionaries.Clear();
var type = typeof(ThemeManager);
var uri = $"{type.Assembly.GetName().Name}.Themes.{themeName}";
var theme = Type.GetType(uri);
Application.Current.Resources.MergedWith = theme;
}
}
}
The above code will clear the existing styles and add the new style based on the theme name.
Step 4 – Create Login Content Page using XAML
For our theming example, we will add two entry fields (Username
and Password
) along with Login button and Select Theme Picker control to our MainPage.xaml.
On selection of theme from the picker control will change the theme of the Login Page (Main Page).
Let's open the MainPage.xaml and modify the XAML as below:
="1.0"="utf-8"
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.MainPage">
<StackLayout Style="{DynamicResource MainStackLayout}">
<Label Text="Login" Style="{DynamicResource LabelPageHeading}"/>
<Label Text="Welcome to Theming Demo" Style="{DynamicResource LabelSubHeading}"/>
<Label Text="Username"/>
<Entry Placeholder="Username"/>
<Label Text="Password" />
<Entry IsPassword="true" Placeholder="Password"/>
<StackLayout Orientation="Horizontal">
<Switch HorizontalOptions="Start" />
<Label Text="Remember me"/>
</StackLayout>
<Button Text="SignIn"/>
<Button Text="Forgot Password?" Style="{DynamicResource ButtonSecondary}"/>
<StackLayout Orientation="Horizontal">
<Label Text="Theme: " VerticalOptions="Center" />
<Picker x:Name="themePicker" Title="Select a theme" HorizontalOptions="Start">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Default</x:String>
<x:String>Pink</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
</StackLayout>
</StackLayout>
</ContentPage>
In the above XAML, note that we have applied the explicit styles using Style
attribute for few controls. For few controls like Entry
and Button
, we have not applied any explicit styles so that they will use Implicit styles.
For Picker
, we have set the Items Source as “Default
” and “Pink
” which is the same as the name of the Style files.
Let's open the MainPage.xaml.cs and modify the C# as below:
using System;
using ThemingDemo.Themes;
using Xamarin.Forms;
namespace ThemingDemo
{
public partial class MainPage: ContentPage
{
public MainPage()
{
InitializeComponent();
themePicker.SelectedIndexChanged += ThemePicker_SelectedIndexChanged;
}
private void ThemePicker_SelectedIndexChanged(object sender, EventArgs e)
{
ThemeManager.ChangeTheme(themePicker.SelectedItem.ToString());
}
}
}
Step 5 – Initialize the Default Style
We have completed most of the steps to change the theme dynamically on selection of theme. However, we will initialize the Default theme when the App runs, and this is done in App.xaml.cs file as shown below:
using ThemingDemo.Themes;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ThemingDemo
{
public partial class App: Application
{
public App()
{
InitializeComponent();
ThemeManager.ChangeTheme("Default");
MainPage = new MainPage();
}
}
}
Step 6 – Run the Project and Test
We are done with the basic theme implementation and it is time to test. Let’s run the project by targeting available emulator and you should be seeing the below Login screen. Note that the application is using default theme which we have created in Default.xaml style file.
Now click on the Theme selector and you should see the below dialog:
Now select “Pink
” style and the screen color scheme is automatically changed to Pink
color as shown below:
Points of Interest
We have seen how to create implicit and explicit styles using XAML Style and apply them dynamically to change the look and feel.
Recently, Xamarin Forms also introduced Cascade Style Sheet (CSS) to create the styles using CSS standards and more information can be found here. Currently, all the styling that's possible with XAML styling cannot be performed with CSS and there is a bug which prevents me from changing the theme dynamically using CSS. So, my focus in this article is mainly XAML styles.
History
- 22nd February, 2019 – Initial version