My friends at UXDivers are doing a great job in bringing Xamarin Forms into the developer's desktop with nicely crafted design and some extra facilities like their Gorilla player which allows you to instantly view your xaml output at design-time.
UXDivers' Grial U.KIT also exposes a wide range of controls and design ideas that enriches applications with ready-made and adaptable Xamarin Forms elements.
Handling fonts with Xamarin Forms
One of the interesting features of Grial is using awesome web font to create attractive buttons design with a minimal resource cost.
As fonts seem to be one interesting resource for applications and, in the same time, are handled differently in target platforms (Android, iOS and Win Phone), I did a small dive into the subject.
My conclusions so far are quite simple:
Styles and Font family naming
As font family naming conventions vary for each platform, the ideal way is to use the Xamarin Forms OnPlatform to define this.
In this example we create an on platform string resource (in App.xaml) with the key "fontNovecentoName":
<OnPlatform x:TypeArguments="x:String"
Android="Novecentowide-Bold.otf"
iOS="Novecentowide-Bold"
WinPhone="./Assets/Fonts/Novecentowide-Bold.otf#Novecento"
x:Key="fontNovecentoName"/>
We can then refer to this font family name in a Label style, like in the following:
<Style TargetType="Label" x:Key="labelNovecento">
<Setter Property="FontFamily" Value="{StaticResource fontNovecentoName}" />
<Setter Property="FontSize" Value="16" />
</Style>
Once we defined this style as an application resource, we can use it anywhere in our xaml views to create labels using the font:
<Label Style="{StaticResource labelNovecento}" Text="This should show Novencento font" />
That label will directly show on iOS and Windows Phone with no extra work.
For Android, we should use a 'Custom renderer' (deriving from Xamarin.Forms LabelRenderer) whose role is to extract the font family name from the xaml code and try to apply it to the target label.
Android custom renderer
'Custom renderers' is a vast subject. To summarize: the role of a custom renderer is to do the job of translating xaml instructions into on-screen graphical items according to each platform constraints. There is a Xamarin built-in renderer for each type of Xamarin Forms controls (Views). If you need an extra rendering job for a control, you create your own renderer inheriting the built-in one for the control… and you override one or more of that built-in renderer's methods to add your specific functionality.
For our subject, we need to create a custom Label renderer in Android to apply the desired font if any is specified.
Sample code:
// we should export our renderer in order to be called
[assembly: ExportRenderer (typeof (Label), typeof (iFontLabelRenderer_Android))]
namespace iFonts.Droid
{
public class iFontLabelRenderer_Android : LabelRenderer
{
// override the base’s OnElementChanged
protected override void OnElementChanged (ElementChangedEventArgs<Label> e)
{
base.OnElementChanged (e);
var label = Control as TextView;
var xfControl = Element as Label;
// try to find the font family name
string fontName= xfControl == null ? null : xfControl.FontFamily;
if(string.IsNullOrEmpty(fontName))
return;
try
{
// try to create and apply the font
Typeface font = Typeface.CreateFromAsset (Forms.Context.Assets, fontName);
label.Typeface = font;
}
catch (Exception)
{
// throw exception if you find this useful
//throw;
}
}
}
}
Download the sample app. iFonts.zip (944.41 kb)