Calligraphy with MvvmCross

Calligraphy isn't working out of the box with MvvmCross. My new NuGet package MvvmCross.Calligraphy brings the simplicity back.

Posted by Sven-Michael Stübe on February 12, 2017

Calligraphy is a nice library that provides custom font handling in Android. I once had issues with the MvvmCross layout inflation and knew that using Calligraphy with MvvmCross will cause some problems and I pushed it onto my Blog todo list - but I was lazy. But this week I saw a question on stackoverflow.

TL;DR

If you just want to get Calligraphy working.

Install-Package MvvmCross.Calligraphy

and modify your Setup.cs

public class Setup : MvxAndroidSetup
{
    protected override MvxAndroidBindingBuilder CreateBindingBuilder()
    {
        return new CalligraphyMvxAndroidBindingBuilder();
    }
} 

done. You don’t need to override AttachBaseContext. And you can setup calligraphy via CalligraphyConfig.InitDefault as documented.

Problem

MvvmCross and Calligraphy are using the same approach for two different things. MvvmCross uses a custom LayoutInflater to provide xml based data binding and Calligraphy uses a custom LayoutInflater that sets the font to TextViews at inflation time. And if you use MvvmCross, the MvvmCross inflater wins.

Why not use Calligraphy Xamarin?

There is already the NuGet package / Xamarin component called Calligraphy Xamarin. But it doesn’t offer the non public class CalligraphyFactory that you need for the fix. If you install it and follow the setup instructions, you will notice, that it won’t have any effect.

How does it work?

The package provides a custom MvxAndroidViewBinder called CalligraphyMvxAndroidViewBinder that applies calligraphy changes for every layout that is inflated with BindingInflate (which should be basically every view). All what’s left, is to put the pieces together. Use CalligraphyMvxAndroidViewFactory to construct it and CalligraphyMvxAndroidBindingBuilder to return the factory in CreateAndroidViewBinderFactory(). In your code you only have to return a new CalligraphyMvxAndroidBindingBuilder in your Setup’s CreateBindingBuilder() method.

public class Setup : MvxAndroidSetup
{
    protected override MvxAndroidBindingBuilder CreateBindingBuilder()
    {
        return new CalligraphyMvxAndroidBindingBuilder();
    }
} 

Conclusion

There is a nice side effect, using the factory directly. You don’t have to wrap every context (Activity, Fragment) with the CalligraphyContextWrapper, because the binding inflater is used globally :) Yay! MvvmCross.Calligraphy on NuGet

Code

The code is available on github mvvmcross-calligraphy. It includes a sample project, too.

If you like the answer, I'd appreciate an upvote ;)
http://stackoverflow.com/a/42184315/1489968
Thanks!


Background Photo by Karen / CC BY
Found a typo? Send me a pull request!