Fonts have received a lot of love from Google in Android O. We’ve already looked at the new custom fonts support which is now backwardly compatible thanks to its inclusion in support library compat v4. However there is another facet to the new fonts support which is really useful: Downloadable Fonts. In this article we’ll take a look at how to use them, and some potential gotchas.
There are actually two main ways that we can use downloadable fonts – the first is programmatically, and the second is purely through XML. I feel that the latter is far more practical for a couple of reasons: Firstly it’s a lot less work! Secondly it is actually much more practical because we can declare required fonts in the Manifest of our app, and the framework can download them ahead of time. If we doit programmatically, we are responsible for initiating the download, which we can only do when the user launches the app – meaning that we’ll need some kind of holding screen while we download the required fonts. This is a poor first experience for the user.
To add a custom font, we must first create a TextView and then in the properties panel of the graphical layout editor we can select the font family drop down, and there is now an option at the bottom of the list for “more fonts…”:
If we select this the import fonts dialog is shown:
We can select the provider for the fonts in the “Source” drop down. Currently only Google Fonts is supported, but there is likely to be more in the future. We then have a selector (including a name search) where we can select our desired font. There are also a series of radio buttons to specify whether we want to declare a downloadable font, or include the font as an asset within our APK. This latter is still a useful option because it will include the mobile-optimised version of the font rather than the non-mobile optimised one we’d download directly from https://fonts.google.com:
If we import this as a download, a number of files are created for us. Firstly there is the font resource definition:
<?xml version="1.0" encoding="utf-8"?> <font-family xmlns:app="http://schemas.android.com/apk/res-auto" app:fontProviderAuthority="com.google.android.gms.fonts" app:fontProviderPackage="com.google.android.gms" app:fontProviderQuery="Pacifico" app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"/>
If you want a full description of what all these fields do, then you can find it in the official documentation. However, I really don’t think we need to know the internals of how the support library /framework is going to retrieve the fonts so we’ll skip a lengthy discussion of this. The provider certificates are used to verify that the provider is who we think it is and is used as a mechanism to prevent a man-in-the middle attack and prevent a third party being able to substitute alternative fonts. These certificates are declared in
The other file that gets created is used to declare which fonts we’d like to framework to preload:
<?xml version="1.0" encoding="utf-8"?> <resources> <array name="preloaded_fonts" translatable="false"> <item>@font/pacifico</item> </array> </resources>
This is then referenced from the Manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.stylingandroid.downloadablefonts"> <application android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" /> </application> </manifest>
Here we reference previously mentioned
That all looks pretty good, except for the final row where the final letter is being clipped slightly. Usually issues such as this can be fixed by adding some additional padding (as discussed here), but that does not work in this case. I suspect that it may be linked to the issue that was mentioned in Fonts (revisited) where there’s bug in applying text styles through XML attributes – this may be affecting the font metrics being calculating when determining the drawable area – so we may see a resolution to this clipping once that other issue gets fixed.
There is one thing to be aware of: If you’re running The Android O Developer Preview 2 (the one that was released during IO 2017) then we get the following:
None of the fonts are being loaded.
Fortunately this has been fixed in Android O Developer Preview 3
So there are still a couple of issues with this, but hen these get resolved using custom fonts will actually get a whole lot easier!
The source code for this article is available here.
© 2017, Mark Allison. All rights reserved.
Copyright © 2017 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.
This doesn’t seem to work on RadioButtons. Did you test that?
I haven’t tried it specifically with RadioButtons, but it should work.