사용 의도
사실 필요한 건 아니었지만 그냥 다크 모드를 대응하기 위해 어떤 것이 필요한지를 공부하고 싶어서 다크 모드를 적용시켜보았다.
학습 내용
공식 문서에 따르면 다크 테마는 API 29 이상(안드로이드 10) 이상에서 제공되며, 다음과 같은 여러 가지 장점이 있다고 한다.
- 전력 사용량을 상당히 절약할 수 있음(기기 화면 기술에 따라 다름)
- 시력이 낮은 사용자와 밝은 빛에 민감한 사용자를 위한 가시성 개선
- 누구나 어두운 환경에서 쉽게 기기 사용 가능
안드로이드 10 이상에서 다크 테마를 활성화하는 방법은 3가지가 존재한다.
- 시스템 설정(설정 → 디스플레이 → 테마)을 사용하여 어두운 테마 활성화
- 빠른 설정 타일을 사용하여 알림 표시줄에서 테마 전환(활성화된 경우)
- Pixel 기기에서 절전 모드를 선택하면 어두운 테마가 동시에 활성화됨(다른 OEM은 이 동작을 지원하거나 지원하지 않을 수 있음)
그런데 메이플 캘린더의 minSdk는 28, 즉 안드로이드 9 이상을 지원하는 앱이다. 따라서 안드로이드 9에서는 다크 테마가 지원되지 않으며 사용자가 직접 테마를 선택하도록 해야 한다.
- 안드로이드 9 이하에서 권장되는 테마 옵션은 다음과 같다.
- 밝은 테마
- 어두운 테마
- 절전 모드에서 설정(권장 기본 옵션)
- 안드로이드 10 이상에서 권장되는 테마 옵션은 다음과 같다.
- 밝은 테마
- 어두운 테마
- 시스템 기본값(권장 기본 옵션)
적용 방법
먼저 values-night라는 이름의 Android Resource Directory를 하나 생성한다.
- values-night에서 theme.xml과 colors.xml 파일을 만든다.
- theme.xml에서 앱의 테마를 DayNight 테마에서 상속하도록 설정한다.
<style name="Base.Theme.MapleCalendar" parent="Theme.Material3.DayNight.NoActionBar">
- colors.xml에서 미리 정의해둔 색상들을 다크 테마일 때 무슨 색으로 바뀌는지 재정의한다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#22000000</color>
<color name="main">#FFF09636</color>
<color name="sub">#FFF6D08A</color>
<color name="alert">#FFB24739</color>
<color name="submit">#FF576AAD</color>
<color name="black1">#99000000</color>
<color name="black2">#88000000</color>
<color name="black3">#66000000</color>
<color name="black4">#55000000</color>
<color name="black5">#44000000</color>
</resources>
- 위 코드는 미리 정의해 둔 색상들이고, 아래 코드는 다크 테마에서 나타나는, 새로 정의한 색상들이다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FFFFFFFF</color>
<color name="white">#FF121212</color>
<color name="gray">#22FFFFFF</color>
<color name="main">#FFC47725</color>
<color name="sub">#FFDBB97B</color>
<color name="alert">#FF8C382D</color>
<color name="submit">#FF3C4978</color>
<color name="black1">#99FFFFFF</color>
<color name="black2">#88FFFFFF</color>
<color name="black3">#66FFFFFF</color>
<color name="black4">#55FFFFFF</color>
<color name="black5">#44FFFFFF</color>
</resources>
이제 xml에 모든 스타일을 정의해두었으니, 다음으로 MainActivity에 버튼 하나를 생성해서 다크 모드/라이트 모드 변환 기능을 추가할 것이다.
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/fab_end"
android:layout_marginBottom="@dimen/fab_bottom"
android:backgroundTint="@color/black"
android:contentDescription="@string/description_fab_dark_mode"
android:onClick="@{() -> vm.setDarkMode()}"
android:src="@drawable/ic_dark_mode"
app:layout_constraintBottom_toTopOf="@id/bnv_main"
app:layout_constraintEnd_toEndOf="parent"
app:tint="@color/white" />
- 본인은 1개의 Activity를 NavHost로써 사용하고, 여러 개의 Fragment를 관리하도록 하였기 때문에, 모든 화면에서 테마 변경 버튼을 좀 자연스럽게(?) 띄워주고 싶어서 Floating Action Button을 추가하였다.
- FAB의 onClick 속성을 정의하여, 버튼 클릭 시 ViewModel에서 정의한 setDarkMode()을 호출한다.
fun setDarkMode() {
viewModelScope.launch {
_lobbyUiEvent.emit(LobbyUiEvent.SetDarkMode)
_calendarUiEvent.emit(CalendarUiEvent.SetDarkMode)
_settingUiEvent.emit(SettingUiEvent.SetDarkMode)
}
}
- SetDarkMode라는 UiEvent를 emit하면, 현재 Activity에 Attach되어있는 Fragment는 해당 UiEvent를 collect하고 다음과 같은 메소드를 호출한다.
protected fun setDarkMode() {
when (MainApplication.mySharedPreferences.getThemeMode("theme", "")) {
getString(R.string.text_light_mode) -> {
MainApplication.mySharedPreferences.setThemeMode("theme", getString(R.string.text_dark_mode))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
getString(R.string.text_dark_mode) -> {
MainApplication.mySharedPreferences.setThemeMode("theme", getString(R.string.text_light_mode))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
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)
}
}
}
}
- 학습 내용에 기록했던 대로, API 버전을 확인하고 29 이상이면 밝은 테마(MODE_NIGHT_NO), 어두운 테마(MODE_NIGHT_YES), 시스템 기본값(MODE_NIGHT_FOLLOW_SYSTEM)을 지원하도록 한다.
- 29 미만, 즉 안드로이드 9 이하라면 시스템 기본값 대신 절전 모드(MODE_NIGHT_AUTO_BATTERY)를 지원한다.
개선점
- 안드로이드 10 이상에서는 시스템 기본값에 따라 모드가 처음에 설정되는데, 이 때 무슨 모드인지 SharedPreferences를 통해서 로컬에 저장해두는 코드를 작성해야 할 것 같다.
결과
버튼을 누르니 테마가 변경되는 것을 확인할 수 있다.
코드
'개인 프로젝트 > 안드로이드' 카테고리의 다른 글
[메이플 캘린더] 위로 스와이프 시 새로고침 기능을 구현해보자 (0) | 2024.01.24 |
---|---|
[메이플 캘린더] RecyclerView로 원하는 달력 View를 만들어보자 (0) | 2024.01.22 |
[메이플 캘린더] AlarmManager로 메붕이들에게 오늘 끝나는 이벤트가 있음을 알려주자 (0) | 2024.01.17 |
[메이플 캘린더] 메이플 캘린더라는 앱을 만들어보았다! 그런데...? (0) | 2024.01.16 |
[개인 프로젝트] 설빙 레시피 앱 #3 (0) | 2022.03.31 |