Variable Fonts are ready to use from Compose UI 1.3.0, for Android O and above.
A variable font is a font that can be customized in multiple ways (or axis or parameters) creating dramatically different styles, while living in a single font file. Those axes can be well known and defined in the standard (e.g.: weight, width, slant, italic) or added by the font itself. Learn more about variable fonts in Google Fonts Knowledge.
From our partners:
By using variable fonts rather than regular font files you only have one font file to manage instead of multiple, containing all the possible font variations.
It allows designers to truly express the brand and developers to be as creative as the font allows, by accessing the whole range of styles with real flexibility to fine-tune it.
In your real app you will have one variable font and customize it to have 3–5 variations, as required by your designs, in a very simple way, always using the same font file.
In this blog we’ll go one step further. With variable fonts, we’ll be able to quickly build an app that dynamically changes the properties of the font and display it, like the following:
For this sample, we’ll be using a variable font called Roboto Flex designed by Font Bureau via Google Fonts.
But there’s many more variable fonts available from Google Fonts. You can find the whole catalog here together with a table of the supported axes per font.
Implementation in Compose
Setup
Firstly, we get the font. At the time of writing, variable fonts are not supported via downloadable fonts (it is an open feature request). So we need to download the font and bundle it in the APK. Make sure that the .ttf file you add is the variable fonts version of the font.
For the Roboto Flex font, the file will be named something like “RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf“ which we rename to “robotoflex_variable.ttf” to add it to Android.
Next up, we add the correct dependencies. Compose UI should be on 1.3.0 or above:
Now, onto the fun part 🎉.
If we check the variable fonts catalog again we’ll see that Roboto Flex can be customized by the following axes:
This information is very important as it contains the different axes names (like XTRA, YTDE etc), min, max and default values. Check the Google Font glossary to know how each axis is able to configure the font.
We’ll select and implement only a subset of 8 Roboto Flex axes in our demo app, while the rest is equivalent.
We start by creating a Composable screen. We add a label and selector (or Slider) for each axis we want to showcase, and define the state for all these selectors by using <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/runtime/MutableState" target="_blank" rel="noopener ugc nofollow">MutableState<T></a>
.
The <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#Slider(kotlin.Float,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.ranges.ClosedFloatingPointRange,kotlin.Int,kotlin.Function0,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.material.SliderColors)" target="_blank" rel="noopener ugc nofollow">Slider</a>
composable takes a valueRange
parameter, that can be easily customized with the font information (min/max values) from the table above. This part of the app will look something like this:
Up until this point, we have all our selectors configured like this:
Predefined axis
Up next, we need to use the selector’s values and configure our font. For this we’ll use the new (experimental) <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/ui/text/font/FontVariation" target="_blank" rel="noopener ugc nofollow">FontVariation</a>
API.
For the predefined axis, <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/ui/text/font/FontVariation.Settings" target="_blank" rel="noopener ugc nofollow">FontVariation</a>
provides predefined methods. For example, we have <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/ui/text/font/FontVariation#weight(kotlin.Int)" target="_blank" rel="noopener ugc nofollow">weight</a>
and <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/ui/text/font/FontVariation#slant(kotlin.Float)" target="_blank" rel="noopener ugc nofollow">slant</a>
which can be set as follows:
Where the values passed for weight and slant were previously defined as <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/runtime/State" target="_blank" rel="noopener ugc nofollow">State</a>
coming from the <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#Slider(kotlin.Float,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.ranges.ClosedFloatingPointRange,kotlin.Int,kotlin.Function0,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.material.SliderColors)" target="_blank" rel="noopener ugc nofollow">Slider</a>
.
Custom axes
For the custom axes, you can use <a class="au le" href="https://developer.android.com/reference/kotlin/androidx/compose/ui/text/font/FontVariation.Settings" target="_blank" rel="noopener ugc nofollow">FontVariation.Settings</a>
method that receives the setting name and value as a parameter. The settings’ names and other relevant information were given by the Google variable fonts catalog we queried earlier. We can configure them like this:
All together now
Finally, we add the new Font to the font family. We create a Text composable, and set the font family. Our main screen will look like this:
In a real app, you’ll probably define the font family in your
<em class="jj">Type.kt</em>
file with static values as opposed to snapshot state variables.
And that’s it! We have our sample app finished, showing how the Roboto Flex variable font is stylized by all its axes.
Best practices
There are two improvements we can do to our code.
For custom axis, we can wrap each in a validation function like the following:
This refactor has a few benefits. Most notably, it validates and prevents misconfiguration of the font by other developers. It also results in a cleaner, more idiomatic syntax altogether.
And secondly, variable fonts are not supported before Android O, therefore this code will crash your app if run in older versions with a runtime IllegalStateException
. To prevent this, we can add a guardrail with a fallback font like this:
Recap
Hope you learned something new, and can incorporate the power of variable fonts to your app.
If you find any bugs or have a feature request, please let us know by filing an issue on our tracker.
Finally, drop all your questions here or on Twitter @astamatok or mastodon and share what you’re building using variable fonts!
Happy Composing! 👋
This post was written with the collaboration of Sean McQuillan on the Jetpack Compose Text team. Thanks to Rebecca Franks and Florina Muntenescu on the DevRel team for their reviews.
By Alejandra Stamato
Source Android
For enquiries, product placements, sponsorships, and collaborations, connect with us at [email protected]. We'd love to hear from you!
Our humans need coffee too! Your support is highly appreciated, thank you!