Mit Schriftarten arbeiten

Auf dieser Seite wird beschrieben, wie Sie Schriftarten in Ihrer Compose-App festlegen.

Schriftart festlegen

Text hat einen fontFamily-Parameter, mit dem die im Compose-Element verwendete Schriftart festgelegt werden kann. Standardmäßig sind die Schriftfamilien Serif, Sans-Serif, Monospace und Cursive enthalten:

@Composable
fun DifferentFonts() {
    Column {
        Text("Hello World", fontFamily = FontFamily.Serif)
        Text("Hello World", fontFamily = FontFamily.SansSerif)
    }
}

Der Text

Mit dem Attribut fontFamily können Sie benutzerdefinierte Schriftarten und Schriftbilder verwenden, die im Ordner res/font definiert sind:

Grafische Darstellung des Ordners „res > font“ in der Entwicklungsumgebung

In diesem Beispiel wird gezeigt, wie Sie eine fontFamily basierend auf diesen Schriftartdateien und mit der Font-Funktion definieren:

val firaSansFamily = FontFamily(
    Font(R.font.firasans_light, FontWeight.Light),
    Font(R.font.firasans_regular, FontWeight.Normal),
    Font(R.font.firasans_italic, FontWeight.Normal, FontStyle.Italic),
    Font(R.font.firasans_medium, FontWeight.Medium),
    Font(R.font.firasans_bold, FontWeight.Bold)
)

Du kannst diesen fontFamily an deine Text komponierbare Funktion übergeben. Da eine fontFamily verschiedene Stärken enthalten kann, können Sie fontWeight manuell festlegen, um die richtige Stärke für Ihren Text auszuwählen:

Column {
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Light)
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Normal)
    Text(
        text = "text",
        fontFamily = firaSansFamily,
        fontWeight = FontWeight.Normal,
        fontStyle = FontStyle.Italic
    )
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Medium)
    Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Bold)
}

Der Text

Informationen zum Festlegen der Typografie in Ihrer gesamten App finden Sie unter Benutzerdefinierte Designsysteme in Compose.

Herunterladbare Schriftarten

Ab Compose 1.2.0 können Sie die API für herunterladbare Schriftarten in Ihrer Compose-App verwenden, um Google Fonts asynchron herunterzuladen und in Ihrer App zu verwenden.

Herunterladbare Schriftarten von benutzerdefinierten Anbietern werden derzeit nicht unterstützt.

Herunterladbare Schriftarten programmatisch verwenden

So laden Sie eine Schriftart programmatisch aus Ihrer App herunter:

  1. Fügen Sie die Abhängigkeit hinzu:

    Groovy

    dependencies {
        ...
        implementation "androidx.compose.ui:ui-text-google-fonts:1.12.1"
    }

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.12.1")
    }
  2. Initialisieren Sie die GoogleFont.Provider mit den Anmeldedaten für Google Fonts:
    val provider = GoogleFont.Provider(
        providerAuthority = "com.google.android.gms.fonts",
        providerPackage = "com.google.android.gms",
        certificates = R.array.com_google_android_gms_fonts_certs
    )
    Der Anbieter erhält die folgenden Parameter:
    • Die Zertifizierungsstelle des Schriftartenanbieters für Google Fonts.
    • Das Paket des Schriftartenanbieters, um die Identität des Anbieters zu bestätigen.
    • Eine Liste von Hash-Sätzen für die Zertifikate, um die Identität des Anbieters zu bestätigen. Die für den Google Fonts-Anbieter erforderlichen Hashes finden Sie in der Datei font_certs.xml in der Jetchat-Beispiel-App.
  3. Definieren Sie einen FontFamily:
    // ...
     import androidx.compose.ui.text.googlefonts.GoogleFont
     import androidx.compose.ui.text.font.FontFamily
     import androidx.compose.ui.text.googlefonts.Font
     // ...
    
    val fontName = GoogleFont("Lobster Two")
    
    val fontFamily = FontFamily(
        Font(googleFont = fontName, fontProvider = provider)
    )
    Sie können andere Parameter für Ihre Schriftart wie Stärke und Stil mit FontWeight bzw. FontStyle abfragen:
    // ...
     import androidx.compose.ui.text.googlefonts.GoogleFont
     import androidx.compose.ui.text.font.FontFamily
     import androidx.compose.ui.text.googlefonts.Font
     // ...
    
    val fontName = GoogleFont("Lobster Two")
    
    val fontFamily = FontFamily(
        Font(
            googleFont = fontName,
            fontProvider = provider,
            weight = FontWeight.Bold,
            style = FontStyle.Italic
        )
    )
  4. Konfigurieren Sie den FontFamily, der in der zusammensetzbaren Funktion „Text“ verwendet werden soll:

Text(
    fontFamily = fontFamily, text = "Hello World!"
)

Sie können auch Typografie definieren, um Ihre FontFamily zu verwenden:

val MyTypography = Typography(
    bodyMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/
    ),
    bodyLarge = TextStyle(
        fontFamily = fontFamily,
        fontWeight = FontWeight.Bold,
        letterSpacing = 2.sp,
        /*...*/
    ),
    headlineMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.SemiBold/*...*/
    ),
    /*...*/
)

Legen Sie als Nächstes die Typografie für das Design Ihrer App fest:

MyAppTheme(
    typography = MyTypography
)/*...*/

Ein Beispiel für eine App, die herunterladbare Schriftarten in Compose zusammen mit Material3 implementiert, finden Sie in der Beispiel-App Jetchat.

Fallback-Schriftarten hinzufügen

Sie können eine Kette von Fallbacks für Ihre Schriftart festlegen, falls die Schriftart nicht richtig heruntergeladen werden kann. Wenn Sie Ihre herunterladbare Schriftart beispielsweise so definiert haben:

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

val fontName = GoogleFont("Lobster Two")

val fontFamily = FontFamily(
    Font(googleFont = fontName, fontProvider = provider),
    Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold)
)

So können Sie die Standardwerte für die Schriftart für beide Schriftstärken definieren:

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

val fontName = GoogleFont("Lobster Two")

val fontFamily = FontFamily(
    Font(googleFont = fontName, fontProvider = provider),
    Font(resId = R.font.my_font_regular),
    Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold),
    Font(resId = R.font.my_font_regular_bold, weight = FontWeight.Bold)
)

Achten Sie darauf, die richtigen Importe hinzuzufügen.

Wenn Sie FontFamily so definieren, wird ein FontFamily mit zwei Ketten erstellt, eine pro Gewichtung. Der Lademechanismus versucht zuerst, die Onlineschriftart aufzulösen, und dann die Schriftart in Ihrem lokalen R.font-Ressourcenordner.

Implementierung debuggen

Um zu prüfen, ob die Schriftart korrekt heruntergeladen wird, können Sie einen Debug-Koroutinen-Handler definieren. Ihr Handle gibt an, was zu tun ist, wenn die Schriftart nicht asynchron geladen werden kann.

Erstellen Sie zuerst eine CoroutineExceptionHandler:

val handler = CoroutineExceptionHandler { _, throwable ->
    // process the Throwable
    Log.e(TAG, "There has been an issue: ", throwable)
}

Übergeben Sie sie an die Methode createFontFamilyResolver, damit der Resolver den neuen Handler verwendet:

CompositionLocalProvider(
    LocalFontFamilyResolver provides createFontFamilyResolver(LocalContext.current, handler)
) {
    Column {
        Text(
            text = "Hello World!", style = MaterialTheme.typography.bodyMedium
        )
    }
}

Sie können auch die isAvailableOnDevice API des Anbieters verwenden, um zu testen, ob der Anbieter verfügbar ist und die Zertifikate richtig konfiguriert sind. Dazu können Sie die Methode isAvailableOnDevice aufrufen, die „false“ zurückgibt, wenn der Anbieter falsch konfiguriert ist.

val context = LocalContext.current
LaunchedEffect(Unit) {
    if (provider.isAvailableOnDevice(context)) {
        Log.d(TAG, "Success!")
    }
}

Vorsichtsmaßnahmen

Es dauert mehrere Monate, bis neue Schriftarten von Google Fonts auf Android-Geräten verfügbar sind. Es gibt eine zeitliche Verzögerung zwischen dem Hinzufügen einer Schriftart in fonts.google.com und ihrer Verfügbarkeit über die API für herunterladbare Schriftarten (entweder im View-System oder in Compose). Neu hinzugefügte Schriftarten werden in Ihrer App möglicherweise nicht geladen und es wird ein IllegalStateException ausgegeben. Damit Entwickler diesen Fehler von anderen Arten von Fehlern beim Laden von Schriftarten unterscheiden können, haben wir in Compose mit den hier beschriebenen Änderungen eine beschreibende Meldung für die Ausnahme hinzugefügt. Wenn Sie Probleme feststellen, melden Sie sie über den Issue Tracker.

Variable Schriftarten verwenden

Eine variable Schriftart ist ein Schriftartformat, bei dem eine Schriftartdatei verschiedene Stile enthalten kann. Bei variablen Schriftarten können Sie Achsen (oder Parameter) ändern, um den gewünschten Stil zu generieren. Diese Achsen können Standardachsen sein, z. B. Gewicht, Breite, Neigung und Kursiv, oder benutzerdefinierte Achsen, die sich je nach variabler Schriftart unterscheiden.

Fünf Konfigurationen derselben variablen Schriftart mit unterschiedlichen Achsenwerten.
Abbildung 1. Text mit derselben variablen Schriftart, die mit unterschiedlichen Achsenwerten angepasst wurde.

Wenn Sie variable Schriftarten anstelle von regulären Schriftartdateien verwenden, benötigen Sie nur eine Schriftartdatei anstelle von mehreren.

Weitere Informationen zu variablen Schriftarten finden Sie unter Google Fonts Knowledge, im gesamten Katalog der verfügbaren variablen Schriftarten und in einer Tabelle der unterstützten Achsen für jede Schriftart.

In diesem Dokument erfahren Sie, wie Sie eine variable Schriftart in Ihrer Compose-App implementieren.

Variable Schriftart laden

  1. Laden Sie die gewünschte variable Schriftart herunter (z. B. Roboto Flex) und legen Sie sie im Ordner app/res/font Ihrer App ab.Die von Ihnen hinzugefügte ttf-Datei muss die variable Schriftartversion der Schriftart sein. Der Name der Schriftartdatei muss vollständig in Kleinbuchstaben geschrieben sein und darf keine Sonderzeichen enthalten.

  2. Wenn Sie eine variable Schriftart laden möchten, definieren Sie eine FontFamily mit der Schriftart im Verzeichnis res/font/:

    // In Typography.kt
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily =
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(950),
                    FontVariation.width(30f),
                    FontVariation.slant(-6f),
                )
            )
        )

    Mit der FontVariation API können Sie Standard-Schriftachsen wie Stärke, Breite und Neigung konfigurieren. Dies sind Standardachsen, die für jede variable Schriftart verfügbar sind. Sie können verschiedene Konfigurationen der Schriftart erstellen, je nachdem, wo die Schriftart verwendet wird.

  3. Variable Schriftarten sind nur für Android-Versionen ab O verfügbar. Fügen Sie daher eine Schutzmaßnahme hinzu und konfigurieren Sie ein geeignetes Fallback:

    // In Typography.kt
    val default = FontFamily(
        /*
        * This can be any font that makes sense
        */
        Font(
            R.font.robotoflex_static_regular
        )
    )
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(950),
                    FontVariation.width(30f),
                    FontVariation.slant(-6f),
                )
            )
        )
    } else {
        default
    }

  4. Extrahieren Sie die Einstellungen in eine Reihe von Konstanten, um sie leichter wiederverwenden zu können, und ersetzen Sie die Schriftarteinstellungen durch diese Konstanten:

    // VariableFontDimension.kt
    object DisplayLargeVFConfig {
        const val WEIGHT = 950
        const val WIDTH = 30f
        const val SLANT = -6f
        const val ASCENDER_HEIGHT = 800f
        const val COUNTER_WIDTH = 500
    }
    
    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(DisplayLargeVFConfig.WEIGHT),
                    FontVariation.width(DisplayLargeVFConfig.WIDTH),
                    FontVariation.slant(DisplayLargeVFConfig.SLANT),
                )
            )
        )
    } else {
        default
    }

  5. Konfigurieren Sie die Typografie von Material Design 3 so, dass FontFamily verwendet wird:

    // Type.kt
    val Typography = Typography(
        displayLarge = TextStyle(
            fontFamily = displayLargeFontFamily,
            fontSize = 50.sp,
            lineHeight = 64.sp,
            letterSpacing = 0.sp,
            /***/
        )
    )

    In diesem Beispiel wird die Material 3-Typografie von displayLarge verwendet, die andere Standardschrifteinstellungen und empfohlene Verwendungen hat. Verwenden Sie beispielsweise displayLarge für kurzen, wichtigen Text, da dies der größte Text auf dem Bildschirm ist.

    Mit Material 3 können Sie die Standardwerte von TextStyle und fontFamily ändern, um die Typografie anzupassen. Im obigen Snippet konfigurieren Sie Instanzen von TextStyle, um die Schrifteinstellungen für jede Schriftfamilie anzupassen.

  6. Nachdem Sie die Typografie definiert haben, übergeben Sie sie an das M3-MaterialTheme:

    MaterialTheme(
        colorScheme = MaterialTheme.colorScheme,
        typography = Typography,
        content = content
    )

  7. Verwenden Sie schließlich ein Text-Composable und geben Sie den Stil als einen der definierten Typografiestile an, MaterialTheme.typography.displayLarge:

    @Composable
    @Preview
    fun CardDetails() {
        MyCustomTheme {
            Card(
                shape = RoundedCornerShape(8.dp),
                elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
            ) {
                Column(
                    modifier = Modifier.padding(16.dp)
                ) {
                    Text(
                        text = "Compose",
                        style = MaterialTheme.typography.displayLarge,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 1
                    )
                    Text(
                        text = "Beautiful UIs on Android",
                        style = MaterialTheme.typography.headlineMedium,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 2
                    )
                    Text(
                        text = "Jetpack Compose is Android’s recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.",
                        style = MaterialTheme.typography.bodyLarge,
                        modifier = Modifier.padding(bottom = 8.dp),
                        maxLines = 3
                    )
                }
            }
        }
    }

    Jedes Text-Composable wird über den Stil des Material-Designs konfiguriert und enthält eine andere Konfiguration für variable Schriftarten. Mit MaterialTheme.typography können Sie die Typografie abrufen, die für die komponierbare M3-Funktion MaterialTheme bereitgestellt wird.

Drei verschiedene Texte, die alle unterschiedliche Schriftkonfigurationen zeigen.
Abbildung 2. Variable Schriftart in drei verschiedenen Konfigurationen.

Benutzerdefinierte Achsen verwenden

Schriftarten können auch benutzerdefinierte Achsen haben. Diese sind in der Schriftartdatei selbst definiert. Die Schriftart Roboto Flex hat beispielsweise die Achse „Höhe der Oberlänge“ ("YTAS"), mit der die Höhe der Oberlängen von Kleinbuchstaben angepasst wird, während mit „Breite der Innenräume“ ("XTRA") die Breite der einzelnen Buchstaben angepasst wird.

Sie können den Wert dieser Achsen mit den FontVariation-Einstellungen ändern.

Weitere Informationen zu den benutzerdefinierten Achsen, die Sie für eine Schriftart konfigurieren können, finden Sie in der Tabelle der unterstützten Achsen für jede Schriftart.

  1. Wenn Sie benutzerdefinierte Achsen verwenden möchten, definieren Sie Funktionen für die benutzerdefinierten Achsen ascenderHeight und counterWidth:

    fun ascenderHeight(ascenderHeight: Float): FontVariation.Setting {
        require(ascenderHeight in 649f..854f) { "'Ascender Height' must be in 649f..854f" }
        return FontVariation.Setting("YTAS", ascenderHeight)
    }
    
    fun counterWidth(counterWidth: Int): FontVariation.Setting {
        require(counterWidth in 323..603) { "'Counter width' must be in 323..603" }
        return FontVariation.Setting("XTRA", counterWidth.toFloat())
    }

    Diese Funktionen haben folgende Aufgaben:

    • Definieren Sie Leitlinien für die Werte, die sie akzeptieren können. Wie Sie im Katalog für variable Schriftarten sehen können, hat ascenderHeight (YTAS) einen Mindestwert von 649f und einen Höchstwert von 854f.
    • Geben Sie die Schriftarteinstellung zurück, damit die Konfiguration der Schriftart hinzugefügt werden kann. In der Methode FontVariation.Setting() ist der Achsenname (YTAS, XTRA) hartcodiert und der Wert wird als Parameter verwendet.
  2. Übergeben Sie mithilfe der Achsen mit der Schriftartenkonfiguration zusätzliche Parameter an jede geladene Font:

    @OptIn(ExperimentalTextApi::class)
    val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        FontFamily(
            Font(
                R.font.robotoflex_variable,
                variationSettings = FontVariation.Settings(
                    FontVariation.weight(DisplayLargeVFConfig.WEIGHT),
                    FontVariation.width(DisplayLargeVFConfig.WIDTH),
                    FontVariation.slant(DisplayLargeVFConfig.SLANT),
                    ascenderHeight(DisplayLargeVFConfig.ASCENDER_HEIGHT),
                    counterWidth(DisplayLargeVFConfig.COUNTER_WIDTH)
                )
            )
        )
    } else {
        default
    }

    Beachten Sie, dass die Höhe der Oberlängen der Kleinbuchstaben jetzt erhöht ist und der andere Text breiter ist:

Drei verschiedene Texte mit unterschiedlichen Konfigurationen für variable Schriftarten, mit benutzerdefinierten Achsen – einige haben höhere Oberlängen bei Kleinbuchstaben und sind breiter als zuvor.
Abbildung 3. Text mit benutzerdefinierten Achsen, die für variable Schriftarten festgelegt wurden.

Zusätzliche Ressourcen

Weitere Informationen finden Sie im folgenden Blogpost zu variablen Schriftarten: