android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.7"
}
}
build.gradle.kts 파일에서 buildFeatures를 통해 compose를 활성화 시키고
composeOptions에서 kotlinCompilerExtensionVersion 옵션을 설정하여 Compose와 함께 사용할 Kotlin 컴파일러 플러그인의 버전을 지정한다.
dependencies {
// compose
val composePlatform = platform("androidx.compose:compose-bom:2023.10.01")
implementation(composePlatform)
}
Bill of Materials(BOM) 방식으로 Compose 관련 의존성들을 관리한다. 여기서 "androidx.compose:compose-bom:2023.10.01"는 Compose 관련 모든 라이브러리들이 2023.10.01 버전과 호환되도록 한다
dependencies {
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
debugImplementation("androidx.compose.ui:ui-tooling")
}
Material Design 3 UI 컴포넌트의 사용을 위한 설정과 함께, 기본적인 UI 기능, 그래픽 처리 기능을 제공하는 라이브러리를 포함하였다. 또한, UI 미리보기를 지원하는 도구와 개발 및 디버깅 과정에서 필요한 Jetpack Compose 관련 도구들을 프로젝트에 추가하였다.
dependencies {
implementation("androidx.activity:activity-compose:1.8.2")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
implementation("androidx.navigation:navigation-compose:2.7.6")
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
}
compose용 viewmodel, navigation, constraintlayout 라이브러리를 사용하여 기존에 작성한 코드에 맞게끔 적용할 것이다.
colors.xml
<resources>
<color name="black">#222227</color>
<color name="gray6">#333232</color>
<color name="gray5">#6A6A6A</color>
<color name="gray4">#949494</color>
<color name="gray3">#D9D9D9</color>
<color name="gray2">#F4F4F4</color>
<color name="gray1">#F9F9F9</color>
...
</resources>
Color.kt
val Black = Color(0xFF222227)
val Gray6 = Color(0xFF333232)
val Gray5 = Color(0xFF6A6A6A)
val Gray4 = Color(0xFF949494)
val Gray3 = Color(0xFFD9D9D9)
val Gray2 = Color(0xFFF4F4F4)
val Gray1 = Color(0xFFF9F9F9)
...
XML 기반의 안드로이드 UI 개발에서는 colors.xml 파일을 통해 앱 전체에서 사용할 색상을 정의하고 관리한다. Jetpack Compose로 마이그레이션할 때는 이러한 색상 정의를 코틀린 코드로 옮겨 Color 객체로 변환해야 한다.
XML의 태그에 정의된 색상 값을 Jetpack Compose에서 사용할 수 있도록 코틀린 파일 내에 Color 객체로 변환하고 있다. 각 XML 색상 값의 16진 코드 앞에 0xFF를 붙여 전체 색상 값으로 만든 후, Color 클래스의 생성자에 전달하여 Compose용 색상 객체를 생성한다.
typography.xml
<resources>
<style name="Typography">
<item name="android:textColor">@color/black</item>
<item name="android:includeFontPadding">false</item>
</style>
<style name="Typography.Title01" parent="Typography">
<item name="fontFamily">@font/pretendard_semi_bold</item>
<item name="android:textSize">24sp</item>
</style>
<style name="Typography.Title02" parent="Typography">
<item name="fontFamily">@font/pretendard_semi_bold</item>
<item name="android:textSize">20sp</item>
</style>
<style name="Typography.Title03" parent="Typography">
<item name="fontFamily">@font/pretendard_semi_bold</item>
<item name="android:textSize">18sp</item>
</style>
<style name="Typography.Body01.Medium" parent="Typography">
<item name="fontFamily">@font/pretendard_medium</item>
<item name="android:textSize">16sp</item>
</style>
...
</resources>
Type.kt
val PretendardSemiBold = FontFamily(Font(R.font.pretendard_semi_bold))
val PretendardMedium = FontFamily(Font(R.font.pretendard_medium))
val PretendardRegular = FontFamily(Font(R.font.pretendard_regular))
val PretendardLight = FontFamily(Font(R.font.pretendard_light))
val defaultTextStyle = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = false,
),
)
val Typography = Typography(
displayLarge = defaultTextStyle.copy(
fontFamily = PretendardSemiBold,
fontSize = 24.sp,
),
displayMedium = defaultTextStyle.copy(
fontFamily = PretendardSemiBold,
fontSize = 20.sp,
),
displaySmall = defaultTextStyle.copy(
fontFamily = PretendardSemiBold,
fontSize = 18.sp,
),
headlineLarge = defaultTextStyle.copy(
fontFamily = PretendardMedium,
fontSize = 16.sp,
),
...
)
Typography를 코드로 직접 정의하여 UI의 텍스트 스타일링을 관리한다. XML 방식에서 typography.xml에 정의된 스타일을 Compose로 마이그레이션하려면, 각 스타일을 TextStyle 객체로 변환해야한다.
typography.xml 파일에 정의된 텍스트 스타일은 style 태그를 사용하여 구성된다. 이러한 스타일들은 텍스트의 색상, 패딩, 글꼴, 텍스트 크기 등을 지정한다. 마이그레이션을 진행할 때, 각 XML 스타일 속성을 Jetpack Compose의 TextStyle 객체와 Typography 클래스로 변환해야한다.
Typography 클래스의 파라미터에 맞게 텍스트 스타일을 지정하였다.
themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.MindSync" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
<item name="android:windowLightStatusBar">true</item>
<item name="android:statusBarColor">@color/white</item>
</style>
<style name="Theme.MindSync" parent="Base.Theme.MindSync" />
</resources>
Theme.kt
private val DarkColorScheme = darkColorScheme(
primary = Gray6,
secondary = Gray4,
tertiary = Gray5,
)
private val LightColorScheme = lightColorScheme()
@Composable
fun MindSyncTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit,
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = Color.White.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content,
)
}
XML에서는 themes.xml을 통해 앱의 테마와 스타일을 정의하지만, Compose에서는 코틀린 코드 내에서 테마를 직접 구성한다.
먼저 색상 스키마 정의한다. DarkColorScheme 및 LightColorScheme 객체를 생성하여 Compose 테마의 어두운 모드와 밝은 모드의 색상을 정의한다. 이 객체들은 primary, secondary, tertiary 등의 색상을 설정한다.
MindSyncTheme 컴포저블 함수를 정의하여 앱의 테마를 설정한다. 이 함수는 darkTheme과 dynamicColor 플래그를 인자로 받아 시스템 테마 설정에 따라 어두운 테마 또는 밝은 테마를 적용한다.
XML | JetapckCompose |
---|---|
XML과 JetpackCompose의 GPU 렌더링을 분석한 결과, XML로 UI를 구현할 때 더 많은 명령어를 사용하기 때문에 처리 시간이 더 오래 걸린다는 것을 확인할 수 있었다.
https://developer.android.com/jetpack/compose/interop/migration-strategy?hl=ko
https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering?hl=ko