본문 바로가기
Jetpack Compose

[Jetpack Compose] Compose에서 폰트시스템(Typography) 구축하기

by JongSeok 2023. 12. 27.

최근 Compose로 신규 안드로이드 앱을 개발하는 프로젝트에 참여하게 되었습니다.

 

본격적인 개발을 시작하기 전 앱 전체에서 사용하게 될 Text의 Style을 지정하기 위해 어떤 방법들이 있나 찾아보았고, 기존에 공부하던 xml 개발 방식과는 다소 차이가 있는 것 같아 공유합니다!


우선 앱에서 사용할 폰트를 다운받아 res font 폴더에 저장합니다.

폰트는 구글에 검색하면 쉽게 다운로드받을 수  있고, .ttf확장자의 대문자를 포함하지 않아야 합니다.

Type.kt

private val nanumSquareRoundStyle = FontFamily(
    Font(R.font.nanum_square_round_regular, weight = FontWeight.Normal),
    Font(R.font.nanum_square_round_bold, weight = FontWeight.Bold)
)

internal val Typography = TellingmeTypography(
    h1Regular = TextStyle(
        fontFamily = nanumSquareRoundStyle,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp
    ),
    h1Bold = TextStyle(
        fontFamily = nanumSquareRoundStyle,
        fontWeight = FontWeight.Bold,
        fontSize = 16.sp,
        lineHeight = 24.sp
    )
)

@Immutable
data class TellingmeTypography(
    val h1Regular: TextStyle,
    val h1Bold: TextStyle
)

val LocalTellingmeTypography = staticCompositionLocalOf {
    TellingmeTypography(
        h1Regular = TextStyle.Default,
        h1Bold = TextStyle.Default
    )
}

먼저 data class 타입의 TellingmeTypography를 정의합니다.

 

기본적으로 정의된 Typography를 그대로 사용해 h1, h2, body1, button 등의 속성만 변경해 사용할 수도 있지만 스타일명도 수정이 안될 뿐 아니라(반드시 override 해야 하는?) 팀에서 준비해 준 많은 종류의 스타일을 사용하기 위해 CustomTypography를 작성합니다.

 

그리고 앱에서 사용할 Typography인 LocalTellingmeTypography를 staticCompositionLocalOf 블럭으로 정의합니다.

Typography는 컴파일 이후 변경되지 않을 데이터이기 때문에 상태를 추적하는 CompositionLocalOf가 아닌 staticCompositionLocalOf을 사용합니다.

 

프로젝트에 추가한 폰트는 FontFamily에 정의합니다.

이때, FontFamily에서 정의된 weight는 TellingmeTypography에서 정의된 TextStyle의 fontWeight와 일치하는 폰트로 Style이 지정됩니다. 

Style에서 R.font.xxx를 직접 찾는 부분이 없어 헤맸는데 참 똑똑하죠?

 

저는 우선 두 가지 스타일만 정의했지만 같은 방법으로 얼마든지 추가가 가능합니다.

Theme.kt

...

@Composable
fun TellingmeTheme(
    ...
) {
    ...
    
    CompositionLocalProvider(LocalTellingmeTypography provides Typography) {
        MaterialTheme(
            colorScheme = colorScheme,
//          typography = Typography,
            content = content
        )
    }
}

object TellingmeTheme {
    val typography: TellingmeTypography
    @Composable
    get() = LocalTellingmeTypography.current
}

이제 앱 전체에서 기존에 제공하는 Typography가 아닌 저희 팀의 스타일을 따르는 TellingmeTypography을 사용할 수 있도록 TellingmeTheme을 사용할 수 있도록 추가합니다.

 

TellingmeTheme의 typography로 Typography가 지정되어 있었지만 Type.kt에서 정의했던 LocalTellingmeTypography로 다시 설정해줬습니다.

 

이렇게 정의한 스타일은 다음과 같이 사용할 수 있습니다 :)

728x90
반응형