글꼴 작업

이 페이지에서는 Compose 앱에서 글꼴을 설정하는 방법을 설명합니다.

글꼴 설정

TextfontFamily 매개변수를 사용하면 컴포저블에 사용되는 글꼴을 설정할 수 있습니다. 기본적으로 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를 정의하는 방법을 보여줍니다. 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)
)

fontFamilyText 컴포저블에 전달할 수 있습니다. 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.7.0"
    }

    Kotlin

    dependencies {
        ...
        implementation("androidx.compose.ui:ui-text-google-fonts:1.7.0")
    }
  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
    )
    드림 제공자가 수신하는 매개변수는 다음과 같습니다. <ph type="x-smartling-placeholder">
      </ph>
    • Google Fonts 글꼴 제공업체 권한
    • 제공업체의 ID를 확인하기 위한 글꼴 제공업체 패키지
    • 제공업체의 ID를 확인하는 인증서의 해시 세트 목록 Google Fonts 제공업체에 필요한 해시를 찾을 수 있습니다. font_certs.xml 파일에서 Jetchat 샘플 앱
  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!"
)

또한 kubectl 명령어 사용할 서체FontFamily:

val MyTypography = Typography(
    bodyMedium = TextStyle(
        fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/
    ),
    bodyLarge = TextStyle(
        fontFamily = fontFamily,
        fontWeight = FontWeight.Bold,
        letterSpacing = 2.sp,
        /*...*/
    ),
    headlineMedium = 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를 사용하여 제공업체를 사용할 수 있는지, 인증서가 올바르게 구성되었는지 테스트할 수도 있습니다. 이렇게 하려면 제공업체가 잘못 구성되었을 때 false를 반환하는 isAvailableOnDevice 메서드를 호출하면 됩니다.

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

주의사항

Google Fonts가 Android에서 새 글꼴을 제공하려면 몇 개월 정도 걸립니다. 글꼴이 추가될 때까지 시간차가 있습니다 fonts.google.com 및 다운로드 가능한 글꼴 API를 제공합니다 (뷰 시스템 또는 Compose에서). 새로 만들기 앱에 추가 글꼴이 로드되지 않을 수도 있습니다 IllegalStateException 개발자가 다른 유형의 글꼴 로드 오류보다 이 오류를 식별할 수 있도록 Compose에 예외에 관한 설명 메시지가 추가되었습니다. 여기를 참조하세요. 문제가 발견되면 문제를 사용하여 신고하세요. 추적기를 사용합니다.

가변 글꼴 사용

가변 글꼴은 하나의 글꼴 파일에 있습니다. 가변 글꼴을 사용하면 축 (또는 매개변수)을 수정하여 선택합니다. 이러한 축은 두께, 너비, 기울기, 기울임꼴과 같은 표준이거나 가변 글꼴마다 다른 맞춤일 수 있습니다.

축 값이 다른 동일한 가변 글꼴의 5가지 구성
그림 1. 다른 축으로 맞춤설정된 동일한 가변 글꼴을 사용하는 텍스트 가치를 제공합니다.

일반 글꼴 파일 대신 가변 글꼴을 사용하면 여러 글꼴 파일 대신 하나의 글꼴 파일만 사용할 수 있습니다.

가변 글꼴에 관한 자세한 내용은 Google Fonts 지식, 사용 가능한 전체 카탈로그 가변 글꼴 및 각 글꼴에 대해 지원되는 축 있습니다.

이 문서에서는 Compose 앱에서 가변 글꼴을 구현하는 방법을 보여줍니다.

가변 글꼴 로드

  1. 사용할 가변 글꼴 (예: Roboto Flex)을 다운로드하고 앱의 app/res/font 폴더에 배치하세요. .ttf 이 파일은 글꼴의 변수 글꼴 버전이며 글꼴 파일은 모두 소문자이고 특수문자가 포함되어 있지 않아야 합니다.

  2. 가변 글꼴을 로드하려면 FontFamily 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),
                )
            )
        )

    FontVariation API를 사용하면 다음과 같은 표준 글꼴 축을 구성할 수 있습니다. 가중치, 너비, 기울기. 이는 모든 가변 글꼴에서 사용할 수 있는 표준 축입니다. 서로 다른 구성을 만들어 사용할 글꼴을 선택합니다.

  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. FontFamily를 사용하도록 Material Design 3 서체를 구성합니다.

    // 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 인스턴스를 사용하여 각 글꼴 모음의 글꼴 설정을 맞춤설정합니다.

  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 Androids 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: 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
    }

    이제 소문자 어센더의 높이가 증가하고 다른 텍스트가 더 넓을 수 있음:

<ph type="x-smartling-placeholder">가변 글꼴의 다양한 구성을 보여주는 세 가지 텍스트. 맞춤 축이 설정되어 있고 일부 텍스트에서는 소문자 어센더가 더 높고 이전보다 폭이 넓어졌습니다. </ph>
그림 3. 가변 글꼴에 설정된 맞춤 축을 보여주는 텍스트

추가 리소스

자세한 내용은 가변 글꼴에 관한 다음 블로그 게시물을 참고하세요.