Using ResourceDictionaries to define Static Resources
Learn how to use ResourceDictionaries in Xamarin.Forms to define our pre-defined font sizes as static resources for your design system components.
Introduction
In the last article we covered defining the colours for our design system components. In this article we'll go into a bit more detail of how ResourceDictionaries work, and what you can do with them.
Like our previous articles we are going to use the Australian Government Design System as our definition for our component set. For our example, we will just define the default font sizes. The following table shows the list of font sizes defined in the guideline:
XXXL |
XXL |
XL |
LG |
MD |
SM |
XS |
Defining Font Sizes in a Xamarin.Forms ResourceDictionary
The first thing we are going to do is define all of our font sizes and line height for the default font set. As per my previous article, I'm putting everything related to fonts, in a seperate Fonts.xaml file.
<?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:Double x:Key="FontDefaultLineSize">1.5</x:Double>
<x:Int16 x:Key="FontDefaultSizeXS">14</x:Int16>
<x:Int16 x:Key="FontDefaultSizeSM">16</x:Int16>
<x:Int16 x:Key="FontDefaultSizeMD">20</x:Int16>
<x:Int16 x:Key="FontDefaultSizeLG">24</x:Int16>
<x:Int16 x:Key="FontDefaultSizeXL">32</x:Int16>
<x:Int16 x:Key="FontDefaultSizeXXL">40</x:Int16>
<x:Int16 x:Key="FontDefaultSizeXXXL">48</x:Int16>
...
You can see from the example above, that we can create both double and short(int16) values. The types that you can use, are defined in the top level namespace declarations i.e. xmlns="http://xamarin.com/schemas/2014/forms". You can even import your own types to be used, but we'll talk through this in a future post.
How to create XAML styles
Now that we've defined the different font sizes and line spacing, we can now access these to define some styles for our different control types.
First we need to reference our external Fonts.xaml file in our App.xaml file, as follows:
<Application.Resources>
<ResourceDictionary Source="Styles/Fonts.xaml"/>
...
Now that we've included our Fonts.xaml file, we can move on to creating our styles. For our example we're going to create new styles for our Xamarin.Forms Label elements.
<Style Class="LabelDefaultXS" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXS}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultSM" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeSM}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultMD" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeMD}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultLG" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeLG}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultXL" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXL}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultXXL" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXXL}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
<Style Class="LabelDefaultXXXL" TargetType="Label">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXXXL}" />
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
Style Inheritance with Xamarin.Forms
As you can see above, we are repeating the setting of the line height property for each label style that we've created. A better way to deal with this repetition is to use style inheritance.
We can inherit any style by using the BasedOn attribute, but first we need to create our new base style with the line height set for the Label.
<Style x:Key="LabelBaseDefault" TargetType="Label">
<Setter Property="LineHeight" Value="{StaticResource FontDefaultLineSize}" />
</Style>
Notice that I've set the x:Key attribute for my base style, this is so that we can reference this style from another style. Now to inherit from the base style, we simply need to reference the base style in the BasedOn attribute of our target style.
<Style Class="LabelDefaultXS" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXS}" />
</Style>
<Style Class="LabelDefaultSM" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeSM}" />
</Style>
<Style Class="LabelDefaultMD" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeMD}" />
</Style>
<Style Class="LabelDefaultLG" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeLG}" />
</Style>
<Style Class="LabelDefaultXL" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXL}" />
</Style>
<Style Class="LabelDefaultXXL" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXXL}" />
</Style>
<Style Class="LabelDefaultXXXL" TargetType="Label" BasedOn="{StaticResource LabelBaseDefault}">
<Setter Property="FontSize" Value="{StaticResource FontDefaultSizeXXXL}" />
</Style>
How to Access ResourceDictionaries from code
At some point you are going to want to access your static resources from your ResourceDictionary from your C# code. To do this simply use Application.Current.Resources to fetch your resource. Here is an example.
var largFontSize = (short)Application.Current.Resources["FontDefaultSizeLG"];
//or
object smallFontSize;
if(Application.Current.Resources.TryGetValue("FontDefaultSizeLG", out smallFontSize)) {
//Do something...
}
Summary
In this article we've covered how to define static resources in an external resource dictionary, and then use those resources to define our Xamarin.Forms styles. We've also show how style inheritance works, and helps us reduce repitition in our styling code.
This is part of my "Implementing a design system in Xamarin.Forms" series of posts.
Contact me at https://www.pattern.co.nz .