Utilizzare i caratteri

In questa pagina viene descritto come impostare i caratteri nell'app Compose.

Imposta carattere

Text ha un parametro fontFamily per consentire l'impostazione del carattere utilizzato nel componibile. Per impostazione predefinita, le famiglie di caratteri serif, senza grazie, monospazio e corsivo sono incluse:

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

Le parole

Puoi utilizzare l'attributo fontFamily per lavorare con caratteri e caratteri tipografici personalizzati definiti nella cartella res/font:

Rappresentazione grafica della cartella dei caratteri res > nell'ambiente di sviluppo

Questo esempio mostra come definire un fontFamily in base a questi file dei caratteri e utilizzando la funzione Font:

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

Puoi passare questo fontFamily al tuo componibile Text. Poiché un fontFamily può includere ponderazioni diverse, puoi impostare manualmente fontWeight per selezionare lo spessore corretto per il testo:

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

Le parole

Per scoprire come impostare la tipografia nell'intera app, vedi Sistemi di progettazione personalizzati in Compose.

Caratteri scaricabili

A partire da Compose 1.2.0, puoi utilizzare l'API dei caratteri scaricabile nell'app Compose per scaricare i caratteri Google in modo asincrono e utilizzarli nella tua app.

Il supporto per i caratteri scaricabili forniti da fornitori personalizzati non è attualmente disponibile.

Utilizza caratteri scaricabili in modo programmatico

Per scaricare un carattere in modo programmatico dall'interno dell'app, segui questi passaggi:

  1. Aggiungi la dipendenza:

    trendy

    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. Inizializza il GoogleFont.Provider con le credenziali per 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
    )
    I parametri ricevuti dal provider sono:
    • L'autorità del fornitore di caratteri per Google Fonts.
    • Il pacchetto del provider di caratteri per verificare l'identità del provider.
    • Un elenco di insiemi di hash per i certificati al fine di verificare l'identità del provider. Puoi trovare gli hash richiesti per il provider di Google Fonts nel file font_certs.xml nell'app Jetchat di esempio.
  3. Definisci un 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)
    )
    Puoi eseguire una query per altri parametri per il tuo carattere, come spessore e stile, rispettivamente con FontWeight e 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. Configura l'elemento FontFamily da utilizzare nella funzione componibile di testo:

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

Puoi anche definire la tipografia per utilizzare i tuoi FontFamily:

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

Quindi, imposta la tipografia sul tema della tua app:

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

Per un esempio di app che implementa caratteri scaricabili in Compose insieme a Material3, vedi l'app di esempio Jetchat.

Aggiungere caratteri di riserva

Puoi determinare una catena di elementi di riserva per il carattere nel caso in cui non venga scaricato correttamente. Ad esempio, se il tuo carattere scaricabile è definito in questo modo:

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

Puoi definire i valori predefiniti del carattere per entrambi gli spessori in questo modo:

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

Assicurati di aggiungere le importazioni corrette.

La definizione di FontFamily in questo modo crea un elemento FontFamily contenente due catene, una per peso. Il meccanismo di caricamento proverà prima a risolvere il carattere online, poi il carattere che si trova nella cartella delle risorse R.font locale.

Esegui il debug dell'implementazione

Per aiutarti a verificare se il carattere viene scaricato correttamente, puoi definire un gestore di coroutine di debug. L'handle indica cosa fare nel caso in cui il carattere non venga caricato in modo asincrono.

Per iniziare, crea un CoroutineExceptionHandler:

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

Passala al metodo createFontFamilyResolver per fare in modo che il resolver utilizzi il nuovo gestore:

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

Puoi anche utilizzare l'API isAvailableOnDevice del provider per verificare se il provider è disponibile e i certificati sono configurati correttamente. Per farlo, puoi chiamare il metodo isAvailableOnDevice, che restituisce false se il provider non è configurato correttamente.

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

Precisazioni

Google Fonts richiede diversi mesi per rendere disponibili nuovi caratteri su Android. C'è un certo ritardo tra il momento in cui un carattere viene aggiunto in fonts.google.com e il momento in cui è disponibile tramite l'API dei caratteri scaricabile (nel sistema di visualizzazione o in Compose). I caratteri appena aggiunti potrebbero non essere caricati nell'app con un elemento IllegalStateException. Per aiutare gli sviluppatori a identificare questo errore rispetto ad altri tipi di errori di caricamento dei caratteri, abbiamo aggiunto dei messaggi descrittivi per l'eccezione in Compose con le modifiche apportate qui. Se riscontri problemi, segnalali utilizzando il tracker problemi.

Utilizza caratteri variabili

Un carattere variabile è un formato di carattere che consente a un file di caratteri di contenere stili diversi. Con i caratteri variabili, puoi modificare gli assi (o i parametri) per generare lo stile che preferisci. Questi assi possono essere standard, ad esempio spessore, larghezza, inclinazione e corsivo, o personalizzati, che differiscono in base al carattere della variabile.

Cinque configurazioni dello stesso carattere variabile con valori dell'asse diversi.
Figura 1. Testo che utilizza lo stesso carattere variabile e personalizzato con valori diversi dell'asse.

L'utilizzo di caratteri variabili invece dei normali file di caratteri ti consente di avere un solo file di carattere anziché più file.

Per ulteriori informazioni sui caratteri variabili, consulta il documento Google Fonts Knowledge, l'intero catalogo di caratteri variabili disponibili e una tabella degli assi supportati per ogni carattere.

Questo documento mostra come implementare un carattere variabile nell'app Compose.

Carica un carattere variabile

  1. Scarica il carattere variabile che vuoi utilizzare (ad esempio Roboto Flex) e inseriscilo nella cartella app/res/font dell'app. Assicurati che il caratterettf Il file che aggiungi è la versione del carattere variabile del carattere e che il nome del file dei caratteri sia tutto minuscolo e non contenga caratteri speciali.

  2. Per caricare un carattere variabile, definisci un carattere FontFamily utilizzando il carattere posizionato nella directory 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),
                )
            )
        )

    L'API FontVariation consente di configurare assi dei caratteri standard come peso, larghezza e inclinazione. Questi sono assi standard disponibili con qualsiasi carattere variabile. Puoi creare diverse configurazioni del carattere in base a dove verrà utilizzato.

  3. I caratteri variabili sono disponibili solo per Android O e versioni successive, quindi aggiungi un sistema di protezione e configura un elemento di riserva appropriato:

    // 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. Estrai le impostazioni in un insieme di costanti per un riutilizzo più semplice e sostituisci le impostazioni del carattere con queste costanti:

    // 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. Configura la tipografia di Material Design 3 per utilizzare FontFamily:

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

    In questo esempio viene usata la tipografia Material 3 displayLarge, che ha diverse impostazioni predefinite per i caratteri e utilizzi consigliati. Ad esempio, dovresti usare displayLarge per un testo breve e critico, perché è il testo più grande sullo schermo.

    Con Material 3, puoi modificare i valori predefiniti di TextStyle e fontFamily per personalizzare la tipografia. Nello snippet riportato sopra, vengono configurate le istanze di TextStyle per personalizzare le impostazioni dei caratteri per ogni famiglia di caratteri.

  6. Ora che hai definito la tipografia, passala all'MaterialTheme M3:

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

  7. Infine, utilizza un componibile Text e specifica lo stile in uno degli stili di tipo definiti, ovvero 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
                    )
                }
            }
        }
    }

    Ogni componibile Text è configurato tramite lo stile del relativo tema Material e contiene una diversa configurazione di carattere variabile. Puoi utilizzare MaterialTheme.typography per recuperare la tipografia fornita al componibile M3 MaterialTheme.

Tre diversi testi, tutti che mostrano configurazioni di caratteri diverse.
Figura 2. Carattere variabile applicato in tre diverse configurazioni.

Utilizza assi personalizzati

I caratteri possono anche avere assi personalizzati. e sono definite all'interno del file dei caratteri. Ad esempio, il carattere Roboto Flex ha l'asse dell'altezza dell'ascender ("YTAS"), che regola l'altezza degli ascensori minuscoli, mentre la larghezza del contatore ("XTRA") regola la larghezza di ogni lettera.

Puoi modificare il valore di questi assi con le impostazioni FontVariation.

Per saperne di più sugli assi personalizzati che puoi configurare per un carattere, consulta la tabella degli assi supportati per ogni carattere.

  1. Per utilizzare gli assi personalizzati, definisci le funzioni per gli assi ascenderHeight e counterWidth personalizzati:

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

    Queste funzioni svolgono le seguenti operazioni:

    • Definire misure di protezione per i valori che possono accettare. Come puoi vedere nel catalogo dei caratteri variabili, ascenderHeight (YTAS) ha un valore minimo di 649f e un massimo di 854f.
    • Restituisci l'impostazione del carattere, in modo che la configurazione sia pronta per essere aggiunta al carattere. Nel metodo FontVariation.Setting(), il nome dell'asse (YTAS, XTRA) è hardcoded e prende il valore come parametro.
  2. Utilizzando gli assi con la configurazione del carattere, passa parametri aggiuntivi a ciascun elemento Font caricato:

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

    Nota che l'altezza degli ascensori minuscoli è ora aumentata e l'altro testo è più largo:

Tre diversi testi che mostrano configurazioni diverse per i caratteri variabili, con assi personalizzati impostati. Alcuni hanno lettere minuscole più alte e sono più larghi rispetto a prima.
Figura 3. Testo che mostra assi personalizzati impostati su caratteri variabili.

Risorse aggiuntive

Per ulteriori informazioni, consulta il seguente post del blog sui caratteri variabili: