개발/Android

Android 10 다크 모드, 다크 테마 적용하기

MiJey 2020. 4. 22. 14:29

Android 10부터 다크 모드를 본격적으로 지원하기 시작했습니다.

여기저기 참고해본 결과 제 생각에 가장 간편하게 다크 모드를 적용하는 방법을 공유해보겠습니다.

 

1. DayNight 테마 적용하기

기본적으로 Light 대신 DayNight 테마만 적용해도 기본 색상(기본 배경색, 기본 글자색 등)이 휴대폰의 다크 모드 옵션을 따라갑니다.

 

DayNight 테마를 적용하는 방법 말고도 style에 forceDarkAllowed 속성의 item을 추가하거나 코드 상에서 setForceDarAllowed로 설정할 수 있습니다. 상황에 따라(ex. 하나의 앱에서 여러 개의 style을 사용하는 경우) 특정 테마에만 다크 모드를 적용할 수 있습니다.

 

// sytles.xml
<item name="android:forceDarkAllowed">true</item>

// in code
view.setForceDarAllowed(true)

 

하지만 이 경우 다크 모드를 어떻게든 지원하기 위해 우겨넣는 느낌이라 새롭게 만드는 앱(또는 규모가 작은 앱)에는 별로 추천하고 싶지 않습니다. 기존 앱에 다크 모드를 적용하는 것은 상황에 따라 융통성 있게 하시면 되겠습니다.

 

검색하다가 참고하면 좋은 글을 발견하여 공유합니다: 원티드 제품 팀블로그 - 안드로이드 앱 다크모드 적용기

 

2. Color Palette 적용하기

다크 테마 머터리얼 디자인 가이드를 참고하여 색상값을 입력해보도록 하겠습니다.

https://material.io/design/color/dark-theme.html#implementation

 

2-1. res/values-night/colors.xml 만들기

res/values에서 오른쪽 버튼 클릭 - New - New Resource File

 

File name은 기존과 동일하게 colors.xml 라고 입력해줍니다.

Directory name은 values-night 라고 입력해줍니다.

OK 버튼을 눌러 파일을 생성합니다.

 

안드로이드 스튜디오에서 자동으로 묶어서 보여줍니다.

 

2-2. colors.xml, styles.xml

일반 모드와 다크 모드에 적용될 색상을 입력해줍니다.

일단은 디자인 가이드 예제 색상을 입력해주었습니다.

 

<!-- res/values/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="Primary">#6200EE</color>
    <color name="PrimaryVariant">#3700B3</color>
    <color name="Secondary">#03DAC6</color>
    <color name="SecondaryVariant">#018786</color>
    <color name="Background">#FFFFFF</color>
    <color name="Surface">#FFFFFF</color>
    <color name="Error">#B00020</color>
    <color name="OnPrimary">#FFFFFF</color>
    <color name="OnSecondary">#000000</color>
    <color name="OnBackground">#000000</color>
    <color name="OnSurface">#000000</color>
    <color name="OnError">#FFFFFF</color>
</resources>

 

<!-- res/values-night/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="Primary">#BB86FC</color>
    <color name="PrimaryVariant">#3700B3</color>
    <color name="Secondary">#03DAC6</color>
    <color name="SecondaryVariant">#018786</color>
    <color name="Background">#121212</color>
    <color name="Surface">#121212</color>
    <color name="Error">#CF6679</color>
    <color name="OnPrimary">#000000</color>
    <color name="OnSecondary">#000000</color>
    <color name="OnBackground">#FFFFFF</color>
    <color name="OnSurface">#FFFFFF</color>
    <color name="OnError">#000000</color>
</resources>

 

2-3. styles.xml

sytles.xml도 바뀐 color name을 적용해줍니다.

 

Primary 색상이 적용되는 것을 확인 할 수 있습니다.

 

3. styles 커스텀 하기

테스트를 위해 values/colors.xml 에는 노란색(#FFFF00), values-night/colors.xml 에는 마젠타(#FF00FF)를 추가해주었습니다. 그리고 styles.xml에 기본 배경 색상에 TestColor를 적용해주었습니다.

 

눈뽕이라 작게 넣음

이런 식으로 status bar, text color 등 다른 기본 색상도 변경할 수 있습니다.

 

4. 테마 사용자 설정

사용자가 OS 기본 설정과 상관 없이 앱의 테마를 고정하고 싶을 때 적용하는 방법입니다.

// 다크 모드 적용 안함
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)

// 다크 모드 적용
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)

// (Android 10 이상) 시스템 설정이 다크 모드일 때 적용
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)

// (Android 10 미만) 배터리 절약 모드일 때 다크 모드 적용
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)

 

클래스를 하나 만들어 설정을 쉽게 적용해보도록 하겠습니다.

 

object ThemeManager {
    enum class ThemeMode { LIGHT, DARK, DEFAULT }

    fun applyTheme(themeMode: ThemeMode) {
        when (themeMode) {
            ThemeMode.LIGHT -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
            ThemeMode.DARK -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
            else ->
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
                } else {
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
                }
        }
    }
}

 

MainActivity에 버튼을 3개 만들고 강제로 Light 테마, Dark 테마를 적용하거나 시스템 설정을 따라가도록 하였습니다.

 

 

SharedPreference 등으로 설정을 저장해두면 시스템 설정과 상관없이 다크 모드 옵션을 제공할 수 있습니다.