#1 일괄적 글꼴 필요
프로젝트 내에서 쓰인 글씨의 크기가 중구난방이라는 문제점이 있다. 현재는, fontSize 속성을 지닌 컴포저블별로 크기값을 일일히 할당해두었기 때문이다. 이를 전체적으로 통제할 수 있어야 한다. 크기 뿐만 아니라, 버튼에 들어가는 용도의 글꼴을 별도로 선언해두었다가 두고두고 쓰는 경우도 앞으로 생길테다.
#2 Typography
#2-1 머터리얼 디자인 가이드
머터리얼 디자인 가이드에서는 일괄적인 글꼴을 제공한다. 게다가, 안드로이드 프로젝트에 기본적으로 통합되어 있다. 그래서 별도의 라이브러리 다운로드 작업없이 즉시 사용할 수 있다. 아래는 그 예시 코드다.
#2-2 Typography 활용 예 1
Text(
text = "Sample Top Bar Text",
style = MaterialTheme.typography.headlineLarge
)
style 속성에 MaterialTheme.typography.headlineLarge (이하 headlineLarge)라는 글꼴을 대입한다. 이 작업은 마치 HTML 태그에 가하는 css 스타일과 비슷하다. 이제부터, 이 Text 컴포저블은 headlineLarge에서 선언한 모양이 된다.
#2-3 Typography 활용 예 2
Text(
text = "Sample Top Bar Text",
fontSize = 20.sp,
style = MaterialTheme.typography.headlineLarge
)
이런 경우에는 1차적으로 headlineLarge에서 선언한 모양을 적용한 후, 2차적으로 fontSize를 적용한다. 즉, fontSize 속성이 우선한다. 전역적인 설정과 지역적인 설정이 충돌했을 때는 이와 같이 지역적인 설정을 우선하는 게 당연하겠지만 말이다.
#2-4 ui.theme.Typography.kt
// package com.example.nutri_capture_new.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
Jetpack Compose 프로젝트를 생성하면 기본으로 들어있는 코드다. 위치는 ui.theme 패키지의 Type.kt 파일이다. Typography 클래스는 bodyLarge, titleLarge, labelSmall, headlineMedium, displaySmall 등등의 수 많은 머터리얼 디자인 글꼴을 생성자로서 받는다. 생성자를 넣지 않으면 각 글꼴은 기본값으로 적용된다. 즉, 머터리얼 디자인 글꼴을 그대로 사용하되 내가 원하는 경우 함수를 오버라이드하듯 커스텀할 수 있다는 얘기다.
내 프로젝트의 경우 아직 글꼴을 다듬는 단계가 아니기에, 우선은 Typography의 기본값을 그대로 사용하겠다. 또 기본값을 사용하는 게 나쁜 것도 아니다. 머터리얼 디자인 권장 사항을 그대로 따르는 것이기 때문이다.
#2-5 참고: Typography 클래스
@Immutable
class Typography(
val displayLarge: TextStyle = TypographyTokens.DisplayLarge,
val displayMedium: TextStyle = TypographyTokens.DisplayMedium,
val displaySmall: TextStyle = TypographyTokens.DisplaySmall,
val headlineLarge: TextStyle = TypographyTokens.HeadlineLarge,
val headlineMedium: TextStyle = TypographyTokens.HeadlineMedium,
val headlineSmall: TextStyle = TypographyTokens.HeadlineSmall,
val titleLarge: TextStyle = TypographyTokens.TitleLarge,
val titleMedium: TextStyle = TypographyTokens.TitleMedium,
val titleSmall: TextStyle = TypographyTokens.TitleSmall,
val bodyLarge: TextStyle = TypographyTokens.BodyLarge,
val bodyMedium: TextStyle = TypographyTokens.BodyMedium,
val bodySmall: TextStyle = TypographyTokens.BodySmall,
val labelLarge: TextStyle = TypographyTokens.LabelLarge,
val labelMedium: TextStyle = TypographyTokens.LabelMedium,
val labelSmall: TextStyle = TypographyTokens.LabelSmall,
) {
...
}
#3 코드
#2-2의 코드대로 기존 프로젝트를 수정한다.
#3-1 MainActivity.kt
...
import androidx.compose.material3.MaterialTheme
...
class MainActivity : ComponentActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
...
setContent {
NutricapturenewTheme {
...
Scaffold(
...
topBar = {
TopAppBar(
title = {
Text(
text = "Sample Top Bar Text",
style = MaterialTheme.typography.headlineLarge
)
}
)
},
bottomBar = {
...
},
snackbarHost = {
SnackbarHost(
...
snackbar = { ...
Snackbar(
...
) {
Text(
text = snackbarData.visuals.message,
style = MaterialTheme.typography.bodyLarge,
)
}
}
)
}
) { ...
...
}
}
}
}
...
}
...
@Composable
fun SampleContent(
...
) {
Box(
...
) {
Button(
...
) {
Text(
text = text,
style = MaterialTheme.typography.headlineMedium
)
}
}
}
#3-2 NutrientScreen.kt
...
import androidx.compose.material3.MaterialTheme
...
@Composable
fun NutrientScreen(
...
) {
...
LazyColumn(
...
) {
item {
FilledTonalButton(
...
) {
Text(
text = "+",
style = MaterialTheme.typography.headlineMedium
)
}
}
...
items(...) { ...
...
Card(
...
) {
Box(
...
) {
Column(
...
) {
Text(
text = DateFormatter.formatDateForNutrientScreen(dayMeal.date) + " " + dayMeal.time,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.End,
style = MaterialTheme.typography.labelLarge
)
Text(
text = "mealId: ${dayMeal.mealId}",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.headlineMedium
)
}
...
}
}
}
}
}
#4 완성된 앱
#4-1 스크린샷
겉모습은 다를 게 거의 없다. 하지만, 내부 코드는 더 깔끔해졌다. 이 시점 이후로 글씨 크기를 지역적으로 할당하는 일이 없도록 해야겠다.
#4-2 이 게시글 시점의 Commit
#4-3 본 프로젝트의 가장 최신 Commit
'App 개발 일지 > Nutri Capture' 카테고리의 다른 글
Nutri Capture 방향성 - 개발 일정표 (1차) (0) | 2024.12.31 |
---|---|
Nutri Capture 프론트엔드 - Dimens와 함께 ChatBar 만들기 (0) | 2024.12.31 |
Nutri Capture 프론트엔드 - bottomBar 동적 변경 (1) | 2024.12.18 |
Nutri Capture 백엔드 - 이진 탐색 적용 (1) | 2024.12.17 |
Nutri Capture 프론트엔드 - item 추가ㆍ제거 애니메이션 (0) | 2024.12.15 |