반응형
개요
컴포즈의 Text
컴포넌트에서 폰트 크기는 아래와 같이 설정할 수 있습니다.
Text(
text = "Android",
fontSize = 16.sp
)
만약 폰트 크기의 단위를 Dp
로 설정한다면 어떻게 될까요?
XML 에서라면 정상적으로 사용이 가능했지만 컴포즈에서는 컴파일 오류가 발생하게 됩니다.
.sp
의 경우, TextUnit
을 반환하지만 .dp
는 Dp
를 반환하기 때문입니다.
@Stable
val Int.sp: TextUnit get() = pack(UNIT_TYPE_SP, this.toFloat())
@Stable
inline val Int.dp: Dp get() = Dp(this.toFloat())
물론 앱 접근성을 확장하기 위해 시스템 폰트 설정에 따라 동적으로 크기가 변하는 Sp
를 권장하고 있지만,
디자인적 이유로 폰트 크기를 고정하고 싶은 경우가 많습니다.
아래 3가지 방법을 통해 컴포즈에서의 폰트 크기를 Dp
로 고정하는 방법을 알아보고자 합니다.
1. Dp to Sp 확장 함수
아래와 같이 LocalDensity
을 활용하여 Dp
를 Sp
로 변환하는 확장함수를
직접 만들어 손쉽게 구현할 수 있습니다.
@Composable
fun dpToSp(dp: Dp): TextUnit = with(LocalDensity.current) { dp.toSp() }
Text(
text = "Android",
fontSize = dpToSp(16.dp)
)
이를 응용하여 앱 테마 내 Typography
를 설정해주는 부분에 적용하게 되면,
불필요한 코드 작성 없이 효율적으로 앱 내 적용이 가능합니다.
private val defaultTypography = Typography()
val Typography
@Composable get() = Typography(
titleLarge = defaultTypography.titleLarge.copy(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Bold,
fontSize = dpToSp(22.dp),
lineHeight = dpTpSp(28.dp),
letterSpacing = dpToSp((-0.02).dp),
),
titleMedium = ...
)
@Composable
fun MyTheme(content: @Composable () -> Unit) {
MaterialTheme(
typography = Typography,
content = content
)
}
2. LocalDensity 를 활용한 fontScale 재계산
LocalDensity
의 fontScale
을 활용하여 현재의 폰트 크기를 시스템 설정에 의한 폰트 크기로
나눠 재계산 해준다면, 1배의 고정된 크기로 Dp 와 같은 효과를 낼 수 있습니다.
val Int.nonScaledSp: TextUnit
@Composable
get() = (this / LocalDensity.current.fontScale).sp
3. LocalDensity 의 fontScale 고정 (CompositionLocalProvider)
마지막은 CompositionLocalProvider
을 활용하여 LocalDensity
내 fontScale
를
직접 1배로 고정시켜주는 방법입니다.
단, 적용된 모든 부분에 대해서 폰트 크기가 고정되기 때문에 사용에 유의해야 합니다.
CompositionLocalProvider(
LocalDensity provides Density(
density = LocalDensity.current.density,
fontScale = 1F
)
) {
MaterialTheme(
colorScheme = LightColorScheme,
typography = Typography,
content = content
)
}
반응형