Swapping Multiple Fonts In Xamarin Android

In this post I’ll be showing you the shortcomings of Android in regards to swapping fonts for views, and some code I’ve written for getting over these shortcomings.

Advertisements

It’s a common practice to switch fonts in whatever project you’re working on, whether a company has a specific typeface they like to use, or whether you just want to use a different font, the fact of the matter is at some point you’re going to need to swap a font out in Android. Here’s the crazy thing, Android, as far as I know, has no real capability to allow you to simply specify an app wide or view hierarchy wide font. This seems insane, but again, as far as I’ve seen, that’s just how it is.

The bad ways to swap fonts

In Android you really have two ways to set the font for an entire layout. Either you specify in your layout file the font you want to use for every last view, or you set the typeface in code. None of these are profoundly great ways of doing this, because either:

You end up writing a bunch of repeated code to swap font faces for every view, which also means a lot of calls to FindViewById, which is slow.

You end up writing a bunch of repeated code for your layouts where every single view has to have a font specified.

The (kind of) good way to swap fonts

So if the normal ways of swapping fonts are bad, is there a good way to swap fonts? Why yes, yes there is, with the help of a font crawler. Before proceeding, I want to mention that early on when I found this code, it was free to use, but I don’t remember the persons name who wrote the post where they initially shared this method. I’ve since made adjustments to the code so it’s different in it’s own right, but if the person who initially shared this method is reading, shoot me an email and I’ll give full credit.

First off, let’s explain the method before I share the code. So in the software world, a crawler basically refers to something that sort of traverses data in a tree-like way, in our case, this means recursively traversing view groups in an Android app. The idea behind this is you pass a view to a method which swaps the font, if the view is a viewgroup, two things hold true:

You can’t set a view groups typeface (relative, linear layout, etc.)

You can assume there is a child view

if the latter is true, this means we can recursively invoke the method, passing the view groups immediate child, and do the same thing as before until we get to a standard view where we can actually swap the font

You may be thinking to yourself “Hey, what if a view doesn’t have a way to swap a font, or what if a type of view has a different way of setting a font?”. Excellent question, let me share the code with you before I explain this in more detail:

 

    public class FontCrawler
    {

        private Typeface typeFace;

        public FontCrawler(Typeface typeface)
        {
            this.typeFace = typeface;
        }

        public FontCrawler(AssetManager assets, String assetsFontFileName)
        {
            typeFace = Typeface.CreateFromAsset(assets, assetsFontFileName);
        }

        public void ReplaceFonts(ViewGroup viewTree)
        {
            if (viewTree != null)
            {

                View child;
                for (int i = 0; i < viewTree.ChildCount; ++i)
                {
                    child = viewTree.GetChildAt(i);
                    if (child is ViewGroup)
                    {
                        // Recursive call to this method, 
                        // Because we have another view group to traverse
                        replaceFonts((ViewGroup)child);
                    }
                    // This is where we actually swap fonts, we'll need to add a 
                    // check for each element that needs it's font swapped.
                    else if (child is TextView)
                    {
                        ((TextView)child).SetTypeface(typeFace, TypefaceStyle.Normal);
                    }

                    else if (child is Button)
                    {
                        ((Button)child).SetTypeface(typeFace, TypefaceStyle.Normal);
                    }
                }
            }
        }

        public void ReplaceViewFont(View view, Typeface tf, TypefaceStyle style)
        {
            if (view is TextView)
            {
                ((TextView)view).SetTypeface(tf, style);
            }

            if (view is Button)
            {
                ((Button)view).SetTypeface(tf, style);
            }
        }

        // For ui elements that don't get a set size at runtime
        public void ReplaceViewFontWithSize(View view, Typeface tf, TypefaceStyle style, float fontSize)
        {
            if (view is TextView)
            {
                ((TextView)view).SetTypeface(tf, style);
                ((TextView)view).SetTextSize(global::Android.Util.ComplexUnitType.Sp, fontSize);
            }

            if (view is Button)
            {
                ((Button)view).SetTypeface(tf, style);
                ((Button)view).SetTextSize(global::Android.Util.ComplexUnitType.Sp, fontSize);
            }
        }

    }

This code is pretty straightforward. First, we instantiate an instance of this font crawler class by passing it a typeface. From there, we use this classes ReplaceFonts method to swap out fonts, and again the way this works is we pass a view group, like a linear layout, and it will traverse the view group until it determines there are no more view groups and only views left. From here, we do a type-check with the is operator to determine how to cast the generic view in order to set the typeface. There is also a method in this class for setting individual views fonts, and there is a method that also sets font sizes for views that are generated on the fly (or if you just need to change the font-size in code for whatever reason).

Conclusion

So that’s really all there is to it, you’ll note my code only swaps fonts for text views and buttons, that’s just because that’s all I’ve ever needed to do, but if you have other views that need fonts swapped out, you can easily just add a check to handle those as well. Hopefully this post, albeit a little shorter than normal, was beneficial, and if you have any feedback let me know by leaving a comment down below, or send me an email and I’ll get back with you asap. Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Advertisements
Advertisements
%d bloggers like this: