안드로이드

(Android) night theme 적용하기

danune.dev 2022. 6. 9. 23:19

Android 에서 Night 테마를 적용하는 방법을 알아보겠습니다 

 

 

1. Night resource 분리

Night theme를 적용하기 위해서는 values-night 폴더에 theme/colors 리소스가 추가되어야 합니다 

먼저 리소스폴더에 values-night 폴더를 생성하고, values 폴더에 있는 themes.xml 과 colors.xml 을 복사해줍니다

 

project의 main 폴더에서 values-night 폴더에 각 파일을 추가하면 아래처럼 파일이 위치하게 됩니다

$ find . -name themes.xml
./res/values/themes.xml
./res/values-night/themes.xml

$ find . -name colors.xml
./res/values/colors.xml
./res/values-night/colors.xml

 

2. resource 내용 수정

2-1. values-night/themes.xml 수정

테마의 parent를 Night 테마로 변경해줍니다. 

기존 parent를 보고 적절하게 변경합니다

기존 parent 변경할 값
Theme.MaterialComponents.DayNight Theme.MaterialComponents.DayNight.DarkActionBar
Theme.AppCompat.DayNight Theme.AppCompat.DayNight.DarkActionBar

 

만약 windowLightStatusBar 가 설정되어있었다면 false 로 변경합니다

<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>

 

최종 theme 내용은 아래와 같습니다 (언급하지 않은 다른 값들은 무시해주세요)

<!-- values-night/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Examples" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <!-- 이부분 변경 -->
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryVariant">@color/color_primary2</item>
<item name="colorOnPrimary">@color/color_text_1</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/color_inverse</item>
<item name="colorSecondaryVariant">@color/color_inverse2</item>
<item name="colorOnSecondary">@color/color_text_inverse_1</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">@color/color_layout_background</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item> <!-- 이부분 변경 -->
</style>
</resources>
<!-- values/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Examples" parent="Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryVariant">@color/color_primary2</item>
<item name="colorOnPrimary">@color/color_text_1</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/color_inverse</item>
<item name="colorSecondaryVariant">@color/color_inverse2</item>
<item name="colorOnSecondary">@color/color_text_inverse_1</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">@color/color_layout_background</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
</resources>
view raw themes.xml hosted with ❤ by GitHub

 

2-2. values-night/colors.xml 수정

취향에 맞게 각 값을 설정합니다 

Night theme가 적용되었을 때 적절하게 어두운 배경에 어두운 텍스트를 보여줄 수 있도록 각 값을 변경합니다

이 예제에서는 몇가지 공통적으로 사용할 값을 설정하였습니다 

<!-- values-night/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_primary">#18181A</color>
<color name="color_primary2">#24242F</color>
<color name="color_primary3">#44444F</color>
<color name="color_accent">#0CFF6F</color>
<color name="color_layout_background">@color/color_primary</color>
<color name="color_item_background">@color/color_primary2</color>
<color name="color_item_selected">#D4D4D4</color>
<color name="color_text_1">#E1E1E1</color>
<color name="color_text_2">#C1C1C1</color>
<color name="color_text_3">#A1A1A1</color>
<color name="color_text_4">#818181</color>
</resources>
<!-- values/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_primary">#EAEAEA</color>
<color name="color_primary2">#FFFFFF</color>
<color name="color_primary3">#DDDDDD</color>
<color name="color_layout_background">@color/color_primary</color>
<color name="color_item_background">@color/color_primary2</color>
<color name="color_item_selected">#4D4D4D</color>
<color name="color_text_1">#313131</color>
<color name="color_text_2">#5A5A5A</color>
<color name="color_text_3">#8d9298</color>
<color name="color_text_4">#A0A0A0</color>
</resources>
view raw colors.xml hosted with ❤ by GitHub

 

 

3. layout/drawable 수정

layout, drawable에 작성한 내용 중 테마를 적용할 곳들의 color를 colors resource를 사용하도록 변경해야합니다 (익숙해지다보면 프로젝트 초기부터 color resource에 정의해서 사용하는 습관을 가지게 됩니다)

예를 들어 아래의 background_item.xml 의 배경색은 @color/color_item_background로 설정하였기 때문에 Light theme에서는 #24242F로, Night theme에서는 #FFFFFF로 보여지기를 기대할 수 있습니다

 

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/color_item_selected">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/color_item_background" />
<corners android:radius="@dimen/radius_large" />
</shape>
</item>
</ripple>

 

4. theme 적용

AppCompatDelegate.setDefaultNightMode method로 테마를 적용할 수 있습니다 

아래 예제에서는 버튼이 눌렸을 때 각각 테마를 설정하도록 하였습니다

각각의 값이 직관적이기때문에 별도의 설명은 생략합니다 

 

class FragmentThemeViewModel {
fun onThemeDefault(view: View) {
setTheme(AppCompatDelegate.MODE_NIGHT_NO)
}
fun onThemeNight(view: View) {
setTheme(AppCompatDelegate.MODE_NIGHT_YES)
}
fun onThemeSystem(view: View) {
setTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
private fun setTheme(mode: Int) {
AppCompatDelegate.setDefaultNightMode(mode)
}
}