How to use Downloadable Fonts with Jetpack Compose

Last updated on: February 16, 2024

In this tutorial, I’m going to show you how to download fonts from Google Fonts and use them in your app.

After a long wait, the Compose library now has downloadable fonts. The feature can be found in version 1.2.0-alpha07 and above.

Adding the library

Go to your module-level gradle.build file, and add the following dependency:

dependencies {
    // ...

    implementation 'androidx.compose.ui:ui-text-google-fonts:1.6.1'

    // ...
}Code language: Kotlin (kotlin)

Setting up Downloadable Fonts

To use Google Fonts in our project, we need to store some credentials to be able to have access to fonts.

Right-click on the values folder, then select New > Values Resource File

In the new window, put font_certs as a file name, and press OK.

Give a name for the xml file of Google Font's credentials

Then, copy the following code and paste it into the file:

<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2022 The Android Open Source Project
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<resources>
    <array name="com_google_android_gms_fonts_certs">
        <item>@array/com_google_android_gms_fonts_certs_dev</item>
        <item>@array/com_google_android_gms_fonts_certs_prod</item>
    </array>
    <string-array name="com_google_android_gms_fonts_certs_dev">
        <item>
            MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
        </item>
    </string-array>
    <string-array name="com_google_android_gms_fonts_certs_prod">
        <item>
            MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
        </item>
    </string-array>
</resources>Code language: HTML, XML (xml)

Next, open the Type.kt file in your app’s ui/theme folder. (When you create a new compose app, Android Studio creates a folder called ui, and inside there, there’s another folder called theme. Here, you’ll find the Type.kt file.)

If you don’t see the Type.kt file in your project, do the following:

From the Project window, select New > Kotlin Class/File

Create a new Kotlin file to set the Google Font's fonts

Then choose File, give it a name (e.g., Type), and press Enter.

Name the Kotlin file Type.kt to set the Google Font's fonts

After that, inside this file, we initialize the GoogleFont.Provider

@OptIn(ExperimentalTextApi::class)
val provider = GoogleFont.Provider(
    providerAuthority = "com.google.android.gms.fonts",
    providerPackage = "com.google.android.gms",
    certificates = R.array.com_google_android_gms_fonts_certs
)Code language: Kotlin (kotlin)

And we set the Google Font we want using the font name from here

// GoogleFont.Provider initialization ...

@OptIn(ExperimentalTextApi::class)
val pacificoFontName = GoogleFont("Pacifico")

@OptIn(ExperimentalTextApi::class)
val pacifico = FontFamily(Font(googleFont = pacificoFontName, fontProvider = provider))
Code language: Kotlin (kotlin)
Type.kt with the GoogleFont.Provider and the downloadable font "Pacifico"

Note: When a new font is added to the Google Font website, it may not be available immediately for use. You may need to wait a few days.

You can also set the font weight and style

// GoogleFont.Provider initialization ...

@OptIn(ExperimentalTextApi::class)
val kanitFontName = GoogleFont("Kanit")

@OptIn(ExperimentalTextApi::class)
val kanitFontFamily = FontFamily(
    Font(googleFont = kanitFontName, fontProvider = provider, weight = FontWeight.Normal),
    Font(googleFont = kanitFontName, fontProvider = provider, weight = FontWeight.ExtraBold, style = FontStyle.Italic),
)Code language: Kotlin (kotlin)
Type.kt with the GoogleFont.Provider and the downloadable font family "Kanit"

Using Downloadable Fonts

Now you can use it like this:

// ...

Column(
modifier = Modifier
.fillMaxSize()
.background(colorResource(id = R.color.colorPrimary))
.wrapContentSize(Alignment.Center)
.padding(padding)
) {

    Text("Text", fontFamily = pacifico, fontSize = 50.sp, color = Color.White)

}

// ...Code language: Swift (swift)

Note: Downloadable fonts do not appear in the Preview

How the downloadable font looks in Jetpack Compose Preview
How the downloadable font looks when the app runs in a device

Using Fallback Fonts

When the user is having trouble connecting to the internet, or there’s a problem connecting to Google’s servers to download the font, Google Font won’t appear correctly. That’s why it’s good to use several fonts as fallbacks.

How we set the fallback fonts doesn’t differ from how we implement a font family.

FontFamily‘s Font list works as a chain, so when the first font fails to load, it will move on to the next one in the list. If that one doesn’t work, it will go to the third one, the fourth, and so on.

You can also add a local font from your R.font resource folder to be 100% sure that the font will be displayed.

Important: Make sure to put the right imports.

import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.googlefonts.Font

// GoogleFont.Provider initialization ...


@OptIn(ExperimentalTextApi::class)
val lobsterTwoFontName = GoogleFont("Lobster Two")

@OptIn(ExperimentalTextApi::class)
val lobsterFontName = GoogleFont("Lobster")

@OptIn(ExperimentalTextApi::class)
val lobsterTwo = FontFamily(
    Font(googleFont = lobsterTwoFontName, fontProvider = provider, weight = FontWeight.Normal),
    Font(resId = R.font.best),
    Font(googleFont = lobsterFontName, fontProvider = provider, weight = FontWeight.Bold),
    Font(resId = R.font.mallent_regular, style = FontStyle.Normal, weight = FontWeight.Normal)
)Code language: Kotlin (kotlin)
Type.kt file with GoogleFont.Provider and downloadable fonts with local fonts that work as fallbacks
You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments