本页介绍了如何在 Compose 应用中设置字体。
设置字体
Text
有一个 fontFamily
参数,用于设置可组合项中使用的字体。默认情况下,系统会添加 Serif、Sans Serif、等宽和 Cursive 字体系列:
@Composable fun DifferentFonts() { Column { Text("Hello World", fontFamily = FontFamily.Serif) Text("Hello World", fontFamily = FontFamily.SansSerif) } }
您可以使用 fontFamily
属性来处理 res/font
文件夹中定义的自定义字体和字型:
以下示例展示了如何根据这些字体文件以及如何使用 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 字体,并在您的应用中使用这些字体。
目前不支持自定义提供程序提供的可下载字体。
以编程方式使用可下载字体
如需从您的应用内以编程方式下载字体,请按以下步骤操作:
- 添加依赖项:
Groovy
dependencies { ... implementation "androidx.compose.ui:ui-text-google-fonts:1.6.7" }
Kotlin
dependencies { ... implementation("androidx.compose.ui:ui-text-google-fonts:1.6.7") }
- 使用 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 提供程序所需的哈希。
- 定义
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) )
您可以分别使用FontWeight
和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 ) )
- 配置要在 Text 可组合函数中使用的
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/*...*/ ), /*...*/ )
接下来,将 Typography 设为应用的主题:
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 中为相应异常添加了描述性消息,并提供了相关更改。如果您发现任何问题,请使用问题跟踪器进行报告。
使用可变字体
可变字体是一种字体格式,它允许一个字体文件包含不同的样式。借助可变字体,您可以修改轴(或参数)以生成首选样式。这些轴可以是标准轴(例如粗细、宽度、斜体和斜体),也可以是自定义轴(因可变字体而异)。
使用可变字体而不是常规字体文件,您可以只有一个字体文件,而不是多个文件。
有关可变字体的更多背景信息,请参阅 Google Fonts 知识、可用可变字体的整个目录,以及每种字体支持的轴的表格。
本文档介绍了如何在 Compose 应用中实现可变字体。
加载可变字体
下载您要使用的可变字体(例如 Roboto Flex),并将其放入应用的
app/res/font
文件夹中。请确保 .您添加的ttf
文件是字体的可变字体版本,字体文件的名称全部为小写,不包含任何特殊字符。如需加载可变字体,请使用放置在
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,您可以配置标准字体轴,例如粗细、宽度和倾斜度。这些是标准轴,可用于任何可变字体。您可以根据字体的使用位置创建不同的字体配置。可变字体仅适用于 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 }
将设置提取到一组常量中以便更轻松地重复使用,并将字体设置替换为以下常量:
// 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 }
配置 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,您可以更改
TextStyle
和fontFamily
的默认值来自定义排版。在上面的代码段中,您配置TextStyle
的实例以自定义每个字体系列的字体设置。现在,您已经定义了排版,将其传递给 M3
MaterialTheme
:MaterialTheme( colorScheme = MaterialTheme.colorScheme, typography = Typography, content = content )
最后,使用
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
可组合项均通过其 Material 主题的样式进行配置,并包含不同的可变字体配置。您可以使用MaterialTheme.typography
检索提供给 M3MaterialTheme
可组合项的排版。
使用自定义轴
字体还可以有自定义轴。这些类型是在字体文件本身中定义的。
例如,Roboto Flex 字体具有上升器高度 ("YTAS"
) 轴,该轴用于调整小写上升器的高度,而计数器宽度 ("XTRA"
) 则用于调整每个字母的宽度。
您可以使用 FontVariation
设置更改这些轴的值。
如需详细了解您可以为字体配置的自定义轴,请参阅每种字体的支持的轴表。
如需使用自定义轴,请为自定义
ascenderHeight
轴和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()) }
这些函数会执行以下操作:
- 为它们可以接受的值定义安全措施。如可变字体目录所示,
ascenderHeight (YTAS)
的最小值为649f
,最大值为854f
。 - 返回字体设置,以便配置可以添加到字体中。在
FontVariation.Setting()
方法中,轴名称 (YTAS, XTRA
) 是硬编码的,它接受值作为参数。
- 为它们可以接受的值定义安全措施。如可变字体目录所示,
使用带有字体配置的轴,将其他参数传递给已加载的每个
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 }
请注意,现在小写的上半部分的高度增加了,而其他文本的宽度也变宽了:
其他资源
如需了解详情,请参阅以下关于可变字体的博文:
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- Compose 中的资源
- 设置文本样式
- Compose 中的 Material Design 2