요즘 좀 치는 앱들은 시스템에서 다크 모드로 전환하면 앱 색상도 그에 대응되어 바뀌는 경우가 많다. (사실 많다기보다는 90% 이상이 아닐까 싶다.) Compose도 당연히 이를 지원하는데, 보통은 MaterialTheme.colorScheme.*
코드를 통해 색상을 가져다 쓰는 경우가 많다.
Box(
modifier = Modifier.background(
color = MaterialTheme.colorScheme.primary
)
) {}
MaterialTheme.colorScheme
를 통해 색상을 지정하면, 굳이 코드에 조건문을 달아주지 않아도 실제 앱 UI에서 다크 모드 대응이 알아서 된다. 여기까지는 좋은데, 문제는 Material 3는 지정된 종류의 색상 외에 사용자가 원하는 다른 색상을 추가할 수 없다는 점이다. (이 부분은 Material 3 색상 구성에 대해 자세히 알고 있어야 이해가 된다. 필요한 분들은 Material 3: Color System 링크를 참고하기 바란다.)
아래에서 별도 클래스 선언을 통해, 다크 모드 대응이 가능한 사용자 지정 색상을 구성할 수 있는 방법을 알아보자.
먼저 사용자 지정 색상 클래스를 선언할 파일을 생성한다. 음, 사실은 굳이 생성 안 해도 되고, 앱 패키지 경로 기준 /ui.theme/Color.kt 파일에 작성해주어도 된다. 새 거 쓰던 헌 거 쓰던 이건 사용자 마음.
private val light_Color1 = Color(0xFF000000)
private val dark_Color1 = Color(0xFF000000)
먼저 클래스 최상단에 사용자 지정 색상을 선언해준다. 여기서 중요한 것은 색상 하나에 대해 라이트 모드에서의 색상, 다크 모드에서의 색상, 총 2가지의 색상을 준비해야 한다는 점이다.
변수의 공개 여부는 사실 크게 중요하지 않다. 코드에서는 private
키워드를 붙여 선언했지만, 실제 개발 때 특정 색상을 다이렉트로 꺼내 쓰고 싶다면 지워주고 공개 변수로 써도 괜찮다.
CustomColor
클래스 선언class CustomColors {
companion object {
private val isDarkTheme: Boolean
@Composable
get() = isSystemInDarkTheme()
}
}
다음으로 사용자 지정 색상을 담을 클래스를 선언한다. 이름은 사용자 마음대로 정하면 된다. 그리고 다크 모드 여부를 판별하기 위해, private
변수로 isDarkTheme
를 선언해준다. isSystemInDarkTheme()
는 시스템의 다크 모드 여부를 반환하는 컴포저블 함수이다.
중요한 점 하나로, 이 색상 클래스는 전역으로 사용할 예정이기 때문에, 반드시 클래스 내에 companion object
블록을 열어 그 안에 모든 색상과 isDarkTheme
변수를 다 몰아 넣어야 한다.
private val light_Color1 = Color(0xFF000000)
private val dark_Color1 = Color(0xFF000000)
class CustomColors {
companion object {
private val darkTheme: Boolean
@Composable
get() = isSystemInDarkTheme()
val Color1: Color
@Composable
get() = if (darkTheme) dark_Color1 else light_Color1
}
}
완성된 코드다.
처음에 클래스 최상단에 선언해 두었던 Raw한 색상들과 조건문을 통해 다크 모드에 대응해준다. 코드가 너무 쉬워서 추가로 설명할 것도 없다.
사실 이건 뭐 문제나 오류의 해결이라기보다는 꿀팁에 가까운 글이었다. 처음에 MaterialTheme.colorScheme
에 직접 색상을 추가해보려다가 실패하고, Getter에 @Composable
어노테이션을 붙일 수 있다는 것도 몰라서 몇 시간 삽질하다 얻은 간단한 해결책이었다.
그리고 추가로 이 글의 내용을 200% 활용하기 위해서는 Material 3 테마를 잘 이해하는 것이 반 필수적이라고 생각한다.
Google이 Jetpack Compose와 Flutter 양쪽에서 Material 3를 활용한 버튼, 박스, 카드, 텍스트 필드 등 다양한 UI 요소를 사용하기 편하도록 소스 코드로 구현해두었기 때문에, Material 3를 잘 이해하고 활용할 경우 학교 과제나 사이드 프로젝트 정도는 높은 완성도로 잘 끝낼 수 있을 거라고 생각한다.
아래의 두 링크를 잘 참고하기 바란다.