使用字型

本頁面說明如何在 Compose 應用程式中設定字型。

設定字型

Text 具有 fontFamily 參數,可設定可組合項中使用的字型。根據預設,Serif、Sans Serif、等寬字型和草寫字型系列都包含

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

主題

您可以使用 fontFamily 屬性,搭配 res/font 資料夾中定義的自訂字型和字體:

開發環境中 res > 字型資料夾的圖形描述

以下範例說明如何根據這些字型檔案以及使用 Font 函式定義 fontFamily

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

您可以將此 fontFamily 傳遞至 Text 可組合項。由於 fontFamily 可包含不同的粗細,因此您可以手動設定 fontWeight,選取適當的文字粗細:

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

主題

如要瞭解如何設定整個應用程式的字體排版,請參閱「Compose 中的自訂設計系統」。

可下載的字型

Compose 1.2.0 開始,您可以使用 Compose 應用程式中的可下載字型 API,以非同步方式下載 Google 字型,並在應用程式中使用。

目前不支援自訂提供者提供的可下載字型。

透過程式輔助方式使用可下載字型

如要在應用程式中以程式輔助方式下載字型,請按照下列步驟操作:

  1. 新增依附元件:

    Groovy

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

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.6.8")
    }
  2. 使用 Google Fonts 的憑證初始化 GoogleFont.Provider
    val provider = GoogleFont.Provider(
        providerAuthority = "com.google.android.gms.fonts",
        providerPackage = "com.google.android.gms",
        certificates = R.array.com_google_android_gms_fonts_certs
    )
    供應商收到的參數如下:
    • Google Fonts 的字型提供者授權。
    • 用於驗證供應者身分的字型提供者套件。
    • 憑證的雜湊組合,用於驗證提供者的身分。您可以在 Jetchat 範例應用程式的 font_certs.xml 檔案中找到 Google Fonts 供應器所需的雜湊。
  3. 定義 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)
    )
    您可以分別使用 FontWeightFontStyle 來查詢字型的其他參數,例如粗細和樣式:
    // ...
     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. 設定要在文字可組合函式中使用的 FontFamily

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

您也可以定義字體排版來使用 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/*...*/
    ),
    /*...*/
)

接著,請將字體排版設為應用程式的主題:

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

如需在 Compose 中搭配 Material3 實作可下載字型的應用程式範例,請參閱 Jetchat 範例應用程式。

新增備用字型

您可以決定字型的備用鏈,以防字型無法正確下載。舉例來說,如果您設定了可下載的字型,如下所示:

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

您可以定義兩個粗細的字型預設值,如下所示:

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

確認您新增的匯入內容正確無誤。

定義這類 FontFamily 會建立一個 FontFamily,其中包含兩個鏈結,每種權重一個。載入機制會先嘗試解析線上字型,然後再解析本機 R.font 資源資料夾中的字型。

為實作偵錯

為協助您確認字型下載是否正確,您可以定義偵錯協同程式處理常式。您的控點提供了字型無法以非同步方式載入時的處理方式。

請先建立 CoroutineExceptionHandler

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

將其傳遞至 createFontFamilyResolver 方法,讓解析器使用新的處理常式:

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

您也可以使用供應商提供的 isAvailableOnDevice API 來測試提供者是否可用,以及憑證設定正確無誤。方法是呼叫 isAvailableOnDevice 方法,如果提供者設定有誤,就會傳回 false。

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

注意事項

Google Fonts 需要數個月的時間,才能在 Android 上提供新字型。在 fonts.google.com 中新增字型後,如要透過可下載的字型 API (無論是在 View 系統或 Compose 中) 取得,都需要時間差。使用 IllegalStateException 載入新增的字型可能無法在應用程式中載入。為協助開發人員找出這類錯誤,而非其他類型的字型載入錯誤,我們針對 Compose 新增了例外狀況說明,並說明這些變更。如有任何問題,請使用 Issue Tracker 回報。

使用可變字型

可變字型是一種字型格式,可讓一個字型檔案包含不同樣式。使用可變字型時,您可以修改軸 (或參數),以產生偏好的樣式。這些軸可以是標準值,例如粗細、寬度、斜體和斜體,也可以是自訂,因不同的字型而異。

具有相同可變字型、不同軸值的五項設定。
圖 1 使用具有不同軸值自訂的相同可變字型的文字。

使用可變字型 (而非一般字型檔案) 可讓您只有一個字型檔案,而非多個字型檔案。

如要進一步瞭解可變字型的背景資訊,請參閱 Google Fonts 知識、可用變數字型整個目錄,以及每種字型支援的軸表格

本文件說明如何在 Compose 應用程式中實作可變字型。

載入變數字型

  1. 下載要使用的變數字型 (例如 Roboto Flex),並放在應用程式的 app/res/font 資料夾中。請確認您新增的 ttf 檔案是字型的「變數字型版本」,其名稱一律為小寫,不含任何特殊字元。

  2. 如要載入變數字型,請使用 res/font/ 目錄中的字型定義 FontFamily

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

    FontVariation API 可讓您設定標準字型軸,例如「weight」、「width」和「slant」。這些是標準軸線,可與任何變數字型搭配使用。您可以根據該字型使用的位置,建立不同的字型設定。

  3. 變數字型僅適用於 Android O 以上版本,因此請新增防護機制並設定適當的備用字型:

    // 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. 將設定擷取為一組常數,以便重複使用,並使用這些常數取代字型設定:

    // 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. 將 Material Design 3 的字體排版設為使用 FontFamily

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

    這個範例採用 displayLarge Material 3 字體排版,其中包含不同的預設字型設定和建議用途。舉例來說,您應針對簡短且重要的文字使用 displayLarge,因為這是螢幕上的最大文字。

    在 Material 3 中,您可以變更 TextStylefontFamily 的預設值,自訂字體排版。在上方的程式碼片段中,您將設定 TextStyle 的執行個體,為每個字型系列自訂字型設定。

  6. 定義字體排版後,請將其傳遞至 M3 MaterialTheme

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

  7. 最後,使用 Text 可組合項,並將樣式指定為其中一個已定義的字體排版樣式 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
                    )
                }
            }
        }
    }

    每個 Text 可組合函式都是透過質感主題的樣式進行設定,並包含不同的變數字型設定。您可以使用 MaterialTheme.typography 擷取提供給 M3 MaterialTheme 可組合項的字體排版。

三種文字,分別顯示不同的字型設定。
圖 2. 已於三種不同設定套用變數字型。

使用自訂軸

字型也可以有自訂軸。這些定義位於字型檔案本身中。舉例來說,Roboto Flex 字型的弧形高度 ("YTAS") 軸,用於調整小寫遞增器的高度,計數器寬度 ("XTRA") 則會調整每個字母的寬度。

您可以透過 FontVariation 設定變更這些軸的值。

如要進一步瞭解您可以為字型設定的自訂軸,請參閱各字型的支援的軸表

  1. 如要使用自訂軸,請定義自訂 ascenderHeightcounterWidth 軸的函式:

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

    這些函式可執行以下作業:

    • 定義防護機制可以接受的值。如同變數字型目錄所示,ascenderHeight (YTAS) 的最小值為 649f,最大值為 854f
    • 傳回字型設定,以便準備將設定加入字型中。在 FontVariation.Setting() 方法中,軸名稱 (YTAS, XTRA) 採用硬式編碼,並將值做為參數。
  2. 搭配使用軸和字型設定,將其他參數傳遞至每個載入的 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
    }

    請注意,小寫遞增器的高度現在會增加,其他文字則更寬:

三則不同的文字分別顯示不同設定,且已設定自訂軸。
圖 3.顯示可變字型設定的自訂軸文字。

其他資源

如需詳細資訊,請參閱下列有關可變字型的網誌文章: