如何使用 Jetpack Compose 将默认字体应用于应用程序中的所有 Text() 元素?

问题描述 投票:0回答:4

我需要对整个应用程序中使用的所有 Text() 应用通用字体。目前,我正在使用如下样式或字体将其手动应用到每个文本。我如何将其指定为应用程序的全局主题?在正常的 xml 布局中,我使用自定义 TextView 小部件来实现此目的。

    Text(
            text = stringResource(id = R.string.userName),
            style = typography.h2,
            fontSize = 20.sp,
        )
android kotlin android-jetpack-compose android-jetpack
4个回答
10
投票

您可以使用

typography
中的
MaterialTheme
参数来指定默认字体。

在Material2中,您可以使用

defaultFontFamily
参数来指定默认字体,如@Ajith所示。但该参数在Material3(Material Design 3)中被删除了。

注意:与 M2 Typography 类不同,M3 Typography 类不 目前包含一个

defaultFontFamily
参数。你需要使用 相反,每个单独的 TextStyle 中的
fontFamily
参数。 (来源

但是您可以对 Material3 执行以下操作。以下是在 M3 中设置默认字体系列的示例:

// Type.kt

import androidx.compose.material3.Typography
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import com.example.exampleapp.R

// Declare the font families
object AppFont {
    val TitilliumWeb = FontFamily(
        Font(R.font.titillium_web_regular),
        Font(R.font.titillium_web_italic, style = FontStyle.Italic),
        Font(R.font.titillium_web_medium, FontWeight.Medium),
        Font(R.font.titillium_web_medium_italic, FontWeight.Medium, style = FontStyle.Italic),
        Font(R.font.titillium_web_bold, FontWeight.Bold),
        Font(R.font.titillium_web_bold_italic, FontWeight.Bold, style = FontStyle.Italic)
    )
}

private val defaultTypography = Typography()
val Typography = Typography(
    displayLarge = defaultTypography.displayLarge.copy(fontFamily = AppFont.TitilliumWeb),
    displayMedium = defaultTypography.displayMedium.copy(fontFamily = AppFont.TitilliumWeb),
    displaySmall = defaultTypography.displaySmall.copy(fontFamily = AppFont.TitilliumWeb),

    headlineLarge = defaultTypography.headlineLarge.copy(fontFamily = AppFont.TitilliumWeb),
    headlineMedium = defaultTypography.headlineMedium.copy(fontFamily = AppFont.TitilliumWeb),
    headlineSmall = defaultTypography.headlineSmall.copy(fontFamily = AppFont.TitilliumWeb),

    titleLarge = defaultTypography.titleLarge.copy(fontFamily = AppFont.TitilliumWeb),
    titleMedium = defaultTypography.titleMedium.copy(fontFamily = AppFont.TitilliumWeb),
    titleSmall = defaultTypography.titleSmall.copy(fontFamily = AppFont.TitilliumWeb),

    bodyLarge = defaultTypography.bodyLarge.copy(fontFamily = AppFont.TitilliumWeb),
    bodyMedium = defaultTypography.bodyMedium.copy(fontFamily = AppFont.TitilliumWeb),
    bodySmall = defaultTypography.bodySmall.copy(fontFamily = AppFont.TitilliumWeb),

    labelLarge = defaultTypography.labelLarge.copy(fontFamily = AppFont.TitilliumWeb),
    labelMedium = defaultTypography.labelMedium.copy(fontFamily = AppFont.TitilliumWeb),
    labelSmall = defaultTypography.labelSmall.copy(fontFamily = AppFont.TitilliumWeb)
)
// Theme.kt

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable

@Composable
fun AppTheme(
    content: @Composable () -> Unit
) {
    MaterialTheme(
        typography = Typography,
        content = content
    )
}

单个组件的示例:

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.example.exampleapp.theme.AppFont

@Composable
fun ExampleScreen() {
    Text(
        text = "Hello World!", 
        fontFamily = AppFont.TitilliumWeb
    )
}

8
投票

Jetpack Compose 支持主题化,可以通过在应用程序主题中指定自定义字体来应用统一字体。执行此操作的步骤如下。

将您的自定义字体复制到 res/font 目录,例如:helvetica_nue.ttf

创建一个 Kotlin 文件 (Type.kt) 并在此处添加您的 Font 系列对象。指定 defaultFontFamily 作为您的自定义字体。如果您希望执行一些额外的自定义,您可以将您的样式添加到 body1 排版中,因为除非指定,否则这是所有 Text() 使用的默认排版。
private val myCustomFont = FontFamily(
    Font(R.font.helvetica_nue),
)


val Typography = Typography(
    defaultFontFamily = myCustomFont,
)
创建一个 Kotiln 文件(Theme.kt 或任何名称)并声明您的应用程序主题
@Composable
fun MyApplicationTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        typography = Typography,
    )
}
在您的活动/片段中,将应用程序的主要可组合项包装在此主题中
 MyApplicationTheme {
            NewsDetailScreen()
        }

现在,无论应用主题,您的应用程序都会以指定字体显示文本。

参考:https://developer.android.com/jetpack/compose/themes/material#typography

如果您想始终使用相同的字体,请指定 defaultFontFamily 参数并省略任何 TextStyle 元素的 fontFamily:


0
投票

一种类似的方法是首先在 Text 可组合项上创建自定义实现,我们将其称为 CustomText。 然后,对于您的用例,您可以在最常用的文本样式上编写包装器,例如

@Composable
TextH2(text : String)  {
 //call your own wrapper over framework Text composable
  CustomText(text = text, typography = h2)
}

为了让事情变得更简单,您可以将字体资源、粗细和大小包装在一起,然后创建此类的具体实现 例如

val h2 = CustomTypography(font = R.font.your-ttf-file, fontSize = 20.sp, fontWeight = Medium)

上面的样式数据在一个可组合项中处理,在我们的例子中是 CustomText。


0
投票

由于这里Material 3的答案是为每种样式单独设置字体,所以我想提出另一种方法。我知道这也不是最好的解决方案,但在 Material 3 提供更好的支持来设置全局字体之前,它可能是更好的解决方案。

此代码片段基于 Android Studio 的默认项目:

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        PlaygroundTheme {
            // A surface container using the 'background' color from the theme

            CompositionLocalProvider(
                LocalTextStyle provides LocalTextStyle.current.merge(
                    TextStyle(fontFamily = FontFamily(
                        Font(R.font.rubik))
                    )
                )
            ) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting("Hello Android!")
                }
            }
        }
    }
}

}

特别注意 CompositionLocalProvider,您可以用另一个本地样式覆盖该样式,只是在这种情况下,该样式将应用于 CompositionLocalProvider 中的所有元素。

© www.soinside.com 2019 - 2024. All rights reserved.