Mit Schriftarten arbeiten

Auf dieser Seite wird beschrieben, wie Sie Schriftarten in der App „Compose“ festlegen.

Schriftart festlegen

Text hat einen fontFamily-Parameter, mit dem die in der zusammensetzbare Funktion verwendete Schriftart festgelegt werden kann. Standardmäßig sind die Schriftfamilien Serif, Sans-Serif, Festbreitenschrift und Kursiv enthalten:

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

Der Text

Sie können das Attribut fontFamily verwenden, um mit benutzerdefinierten Schriftarten und Schriftbildern zu arbeiten, 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 definieren und die Funktion Font verwenden:

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)
)

Sie können diese fontFamily an Ihre zusammensetzbare Funktion Text übergeben. Da eine fontFamily verschiedene Gewichtungen enthalten kann, können Sie fontWeight manuell festlegen, um die richtige Gewichtung 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 herunterladbare Fonts API in Ihrer Compose-Anwendung verwenden, um Google-Schriftarten asynchron herunterzuladen und in Ihrer Anwendung zu verwenden.

Derzeit werden von benutzerdefinierten Anbietern herunterladbare Schriftarten nicht unterstützt.

Herunterladbare Schriftarten programmatisch verwenden

Gehen Sie folgendermaßen vor, um eine Schriftart programmatisch aus Ihrer App herunterzuladen:

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

    Groovig

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

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.6.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 folgende Parameter:
    • Die Schriftartanbieter für Google Fonts.
    • Das Paket des Schriftartanbieters zur Überprüfung der Identität des Anbieters.
    • Eine Liste mit Hashes 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 die Schriftart abfragen, z. B. Schriftstärke und Stil mit FontWeight bzw. FontStyle:
    // ...
     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 die FontFamily, die in der zusammensetzbaren Textfunktion verwendet werden soll:

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

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

val MyTypography = Typography(
    labelMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/
    ),
    labelLarge = TextStyle(
        fontFamily = fontFamily,
        fontWeight = FontWeight.Bold,
        letterSpacing = 2.sp,
        /*...*/
    ),
    displayMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.SemiBold/*...*/
    ),
    /*...*/
)

Stellen Sie als Nächstes die Typografie auf das Design Ihrer App ein:

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

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

Fallback-Schriftarten hinzufügen

Sie können eine Kette von Fallbacks für die Schriftart festlegen, falls die Schriftart nicht ordnungsgemäß heruntergeladen werden kann. Wenn Ihre herunterladbare Schriftart zum Beispiel so definiert ist:

// ...
 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)
)

Sie können die Standardwerte für Ihre Schriftart für beide Schriftstärken wie folgt 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, dass Sie die richtigen Importe hinzufügen.

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

Implementierungsfehler beheben

Damit Sie überprüfen können, ob die Schriftart korrekt heruntergeladen wird, können Sie einen Debug-Coroutine-Handler definieren. Der 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 ihn 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!")
    }
}

Einschränkungen

Es dauert mehrere Monate, bis Google Fonts neue Schriftarten für Android zur Verfügung stellt. Es gibt eine zeitliche Lücke zwischen dem Hinzufügen einer Schriftart auf fonts.google.com und der Verfügbarkeit über die herunterladbare Fonts API (entweder im Ansichtssystem oder in Compose). Neu hinzugefügte Schriftarten werden möglicherweise nicht mit einem IllegalStateException in Ihre Anwendung geladen. Damit Entwickler diesen Fehler im Vergleich zu anderen Arten von Fehlern beim Laden von Schriftarten leichter erkennen können, haben wir unter Verfassen der Änderungen hier beschreibende Hinweise für die Ausnahme hinzugefügt. Wenn Sie Probleme finden, melden Sie diese über die Problemverfolgung.

Variable Schriftarten verwenden

Eine variable Schriftart ist ein Schriftformat, mit dem eine Schriftartdatei verschiedene Stile enthalten kann. Mit variablen Schriftarten können Sie Achsen (oder Parameter) ändern und Ihren bevorzugten Stil generieren. Dabei kann es sich um Standardachsen handeln, z. B. Gewichtung, Breite, Neigung und Kursivschrift, oder benutzerdefinierte Achsen, die sich je nach Schriftart unterscheiden.

Fünf Konfigurationen derselben Variablenschrift mit unterschiedlichen Achsenwerten.
Abbildung 1: Text mit derselben Schriftart, der mit unterschiedlichen Achsenwerten angepasst ist

Wenn Sie anstelle von normalen Schriftartdateien variable Schriftarten verwenden, können Sie anstatt mehrerer Schriftarten nur eine einzige Schriftdatei haben.

Weitere Informationen zu variablen Schriftarten finden Sie unter Google Fonts Knowledge, im gesamten Katalog verfügbarer Variablenschriftarten und in einer Tabelle mit den unterstützten Achsen für die einzelnen Schriftarten.

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

Variablenschrift laden

  1. Laden Sie die Schriftart der Variablen, die Sie verwenden möchten (z. B. Roboto Flex) herunter und speichern Sie sie im Ordner app/res/font Ihrer App. Die .ttf ist die Variable Schriftartversion der Schriftart und der Name der Schriftartdatei muss kleingeschrieben sein und keine Sonderzeichen enthalten.

  2. Wenn Sie eine variable Schriftart laden möchten, definieren Sie einen FontFamily. Verwenden Sie dazu die 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 Standardschriftachsen wie Gewichtung, Breite und Neigung konfigurieren. Dies sind Standardachsen, die in jeder variablen Schriftart verfügbar sind. Sie können verschiedene Konfigurationen der Schriftart erstellen, je nachdem, wo sie verwendet wird.

  3. Variable Schriftarten sind nur für die Android-Version O und höher 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 zur einfacheren Wiederverwendung in einen Satz von Konstanten 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 Material Design 3-Typografie 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 displayLarge Material 3-Typografie verwendet, die andere Standardschrifteinstellungen und empfohlene Verwendungen bietet. Du solltest beispielsweise displayLarge für kurzen, wichtigen Text verwenden, da dies der größte Text auf dem Bildschirm ist.

    Bei Material 3 kannst du die Standardwerte von TextStyle und fontFamily ändern, um deine Typografie anzupassen. Im Snippet oben konfigurieren Sie Instanzen von TextStyle, um die Schriftarteinstellungen 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 eine zusammensetzbare Funktion Text und geben Sie als Stil einen der definierten Typografiestile MaterialTheme.typography.displayLarge an:

    @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
                    )
                }
            }
        }
    }

    Jede zusammensetzbare Funktion (Text) wird anhand des Stils ihres Material-Designs konfiguriert und enthält eine andere variable Schriftartkonfiguration. Mit MaterialTheme.typography können Sie die Typografie abrufen, die der M3- zusammensetzbaren Funktion MaterialTheme zur Verfügung gestellt wurde.

Drei verschiedene Texte mit unterschiedlichen Schriftartkonfigurationen.
Abbildung 2. Variable Schriftart wird in drei verschiedenen Konfigurationen angewendet.

Benutzerdefinierte Achsen verwenden

Schriftarten können auch benutzerdefinierte Achsen haben. Diese werden in der Schriftartdatei selbst definiert. Die Schriftart Roboto Flex hat beispielsweise die Achse für die Höhe ("YTAS") für die Oberlänge, mit der die Höhe der Oberstriche in Kleinbuchstaben angepasst wird, während die Zählerbreite ("XTRA") die Breite der einzelnen Buchstaben anpasst.

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 die jeweilige 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 führen folgende Schritte aus:

    • Legen Sie Leitlinien für die zulässigen Werte fest. Wie Sie im Katalog für Variablenschriften 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 zur Schriftart hinzugefügt werden kann. Bei der Methode FontVariation.Setting() ist der Achsenname (YTAS, XTRA) hartcodiert und verwendet den Wert als Parameter.
  2. Übergeben Sie mithilfe der Achsen mit der Schriftartkonfiguration zusätzliche Parameter an jedes 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 Oberteile in Kleinbuchstaben jetzt erhöht und der andere Text breiter ist:

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

Weitere Informationen

Weitere Informationen finden Sie im folgenden Blogpost zu variablen Schriftarten: