Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / XAML

Xamarin Forms - Theming Made Simple

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
21 Feb 2019CPOL4 min read 20.4K   457   10   4
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.

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.

Image 1

In the New Project windows, Choose Cross-Platform-->Mobil App (Xamarin Forms) as shown below:

Image 2

Enter the project name as Theming Demo and Click OK, the below option dialog will be displayed:

Image 3

In the above screen, select Blank Project and click OK, the below project will be created.

Image 4

Select the emulator and run the project, you should be able to see the Main Page with welcome text as below:

Image 5

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:

Image 6

Once the file is added, open the Default.xaml.cs file and replace the “ContentPage” with “ResourceDictionary” as shown below:

C#
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:

XML
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.Themes.Default">
<!--Implicit Styles-->
<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>
<!--Explicit Styles - a Key is Added - Must be referred by Style="{DynamicResource MainStackLayout}" -->
<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:

XML
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
 x:Class="ThemingDemo.Themes.Pink">
<!--Implicit Styles-->
<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>
<!--Explicit Styles - a Key is Added - Must be referred by Style="{DynamicResource MainStackLayout}" -->
<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:

Image 7

Step 3 – Create Theme Manager Helper

Create a new helper class called ThemeManager and add a public method ChangeTheme with signature as below:

C#
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:

XML
<?xml version="1.0" encoding="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:

C#
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:

C#
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"); //Initialize the Default Theme
            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.

Image 8

Now click on the Theme selector and you should see the below dialog:

Image 9

Now select “Pink” style and the screen color scheme is automatically changed to Pink color as shown below:

Image 10

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect EVRY (india) Private Limited
India India
TOGAF 9 Certified professional, has over 19+ years of experience in Information technology with experience in providing solution architecture, designing, implementing effective technical business solutions using Architecture Development Methodologies (ADM), Technical Leadership, Software Development and Project Leadership based on Microsoft .Net and JavaScript Technologies

Comments and Discussions

 
BugMergedWidth obsolete Pin
Member 1295801621-May-22 7:58
Member 1295801621-May-22 7:58 
QuestionPreferences Pin
Member 1509834712-Mar-21 1:14
Member 1509834712-Mar-21 1:14 
QuestionPreferences Pin
Member 1509834712-Mar-21 1:09
Member 1509834712-Mar-21 1:09 
How to give preferences to above select theme like once the user selected one theme that should be saved even after closing and reopening the app again
PraiseVery good articel! Is the CSS in xamarin in the meanwhile usable? Pin
Member 1053406626-Jul-20 21:45
Member 1053406626-Jul-20 21:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.