본문 바로가기
요모조모 정보

안드로이드 다크 모드 화면 개발! 화면 모드 체크 및 변경사항 적용 시 참고사항

by Kongkongpapa 2025. 4. 22.
728x90
반응형
SMALL

최근 몇 년간 다크 모드는 사용자들의 눈 건강 보호, 배터리 절약, 그리고 단순히 어두운 테마를 선호하는 사용자들의 증가로 인해 중요한 UI/UX 요소로 자리 잡았습니다. 안드로이드 앱 개발에서도 다크 모드를 지원하는 것은 이제 필수적인 고려 사항이 되었습니다.

이번 글에서는 안드로이드 앱에서 다크 모드 화면을 개발하는 방법에 대해 심도 있게 알아보겠습니다.

1. 시스템 다크 모드 확인

앱이 현재 다크 모드로 표시되어야 하는지 확인하는 첫 번째 단계는 시스템의 다크 모드 설정을 확인하는 것입니다. AppCompatDelegate를 사용하는 경우, localNightMode를 MODE_NIGHT_FOLLOW_SYSTEM으로 설정한 후 이를 통해 시스템의 다크 모드 상태를 가져올 수 있습니다.

Kotlin
 
import android.content.res.Configuration
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate

class MyActivity : AppCompatActivity() {

    private fun isSystemInDarkMode(): Boolean {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
        return AppCompatDelegate.getLocalNightMode() == AppCompatDelegate.MODE_NIGHT_YES
    }

    // ...
}

이 함수는 localNightMode를 시스템 설정을 따르도록 설정한 후, 현재 localNightMode가 다크 모드(MODE_NIGHT_YES)인지 확인하여 시스템이 다크 모드이면 true를 반환합니다.

2. uiMode 설정 및 처리

앱이 다크 모드 설정을 변경할 때 액티비티가 어떻게 반응할지 제어하기 위해 매니페스트 파일에서 <activity> 태그에 android:configChanges="uiMode" 속성을 추가할 수 있습니다.

XML
 
<activity
    android:name=".MyActivity"
    android:configChanges="uiMode">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

uiMode를 설정하면 시스템 다크 모드 전환 시 액티비티가 재시작되는 대신 onConfigurationChanged() 콜백 메서드가 호출됩니다. 이 메서드에서 다크 모드 변경에 따른 UI 업데이트 로직을 구현해야 합니다.

Kotlin
 
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_YES -> {
            // 다크 모드로 변경됨
            applyDarkModeUI()
        }
        Configuration.UI_MODE_NIGHT_NO -> {
            // 라이트 모드로 변경됨
            applyLightModeUI()
        }
    }
}

private fun applyDarkModeUI() {
    // 다크 모드에 맞는 색상이나 스타일 적용
}

private fun applyLightModeUI() {
    // 라이트 모드에 맞는 색상이나 스타일 적용
}

3. 프로그래밍 방식으로 테마 변경

앱 내에서 특정 조건에 따라 다크 모드를 활성화하거나 비활성화하고 싶을 때는 프로그래밍 방식으로 테마를 변경할 수 있습니다.

3.1. recreate() 사용

가장 간단한 방법은 액티비티의 recreate() 메서드를 호출하는 것입니다. 이는 액티비티를 다시 시작시켜 onCreate() 메서드를 다시 호출하게 됩니다. 테마를 변경한 후 recreate()를 호출하면 새로운 테마가 적용된 UI를 볼 수 있습니다.

Kotlin
 
// UI 모드를 변경하는 로직 (예: 설정 값 변경)

if (isDarkMode()) {
    setTheme(R.style.Theme_MyApp_Dark)
} else {
    setTheme(R.style.Theme_MyApp)
}

recreate()

3.2. onConfigurationChanged() 직접 호출 (고급)

더욱 세밀한 제어를 원한다면 테마를 변경한 후 onConfigurationChanged() 메서드를 직접 호출할 수도 있습니다. 이 방법은 액티비티가 매니페스트에서 uiMode를 처리하도록 선언되어 있어야 합니다.

Kotlin
 
// UI 모드를 변경하는 로직

if (isDarkMode()) {
    setTheme(R.style.Theme_MyApp_Dark)
} else {
    setTheme(R.style.Theme_MyApp)
}

val newConfig = Configuration(resources.configuration).apply {
    uiMode = (uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()) or
            (if (isDarkMode()) Configuration.UI_MODE_NIGHT_YES else Configuration.UI_MODE_NIGHT_NO)
}
onConfigurationChanged(newConfig)

4. 스타일 테마와 다크 모드 상태

앱의 스타일 테마는 다크 모드 상태를 결정하는 데 중요한 역할을 합니다. Theme.AppCompat.DayNight와 같은 테마를 사용하면 앱은 시스템 설정에 따라 자동으로 다크 모드를 전환할 수 있습니다. values/themes.xml과 values-night/themes.xml 파일을 통해 각각 라이트 모드와 다크 모드에 대한 스타일을 정의할 수 있습니다.

5. 명시적으로 라이트 테마를 사용하는 경우

Theme.AppCompat.Light와 같이 라이트 테마를 명시적으로 사용하는 앱에서도 시스템의 다크 모드 설정을 확인할 수 있습니다. 이 경우 앱은 항상 라이트 모드로 표시되지만, 시스템 설정을 기반으로 특정 동작을 수행할 수 있습니다.

Kotlin
 
val isSystemDarkMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES

6. localNightMode와 defaultNightMode의 차이

AppCompatDelegate에는 localNightMode와 defaultNightMode라는 두 가지 주요 야간 모드 설정이 있습니다.

  • defaultNightMode: 앱 전체에 적용되는 기본 야간 모드 설정을 나타냅니다. AppCompatDelegate.setDefaultNightMode() 메서드를 사용하여 설정할 수 있습니다. 이 설정은 앱의 모든 액티비티에 기본적으로 적용됩니다.
  • localNightMode: 특정 AppCompatDelegate 인스턴스(일반적으로 액티비티)에 대한 야간 모드 설정을 오버라이드합니다. AppCompatDelegate.setLocalNightMode() 메서드를 사용하여 설정할 수 있습니다. localNightMode는 해당 특정 액티비티에만 영향을 미치며, defaultNightMode보다 우선합니다.

defaultNightMode를 MODE_NIGHT_FOLLOW_SYSTEM으로 설정하면 앱은 기본적으로 시스템의 다크 모드 설정을 따릅니다. 이후 특정 액티비티에서 localNightMode를 다른 값으로 설정하면 해당 액티비티는 defaultNightMode 대신 자신의 설정을 사용합니다.

예를 들어, 특정 설정 화면에서 사용자가 앱의 야간 모드를 강제로 켜거나 끄도록 할 수 있는데, 이때 해당 액티비티에서 localNightMode를 설정하면 됩니다.

결론

안드로이드 앱에서 다크 모드를 지원하는 것은 사용자 경험을 향상시키는 중요한 요소입니다. 시스템 설정을 활용하거나 프로그래밍 방식으로 테마를 변경하고 uiMode 설정 및 AppCompatDelegate의 설정을 통해 섬세하게 UI를 제어함으로써 사용자에게 최적의 시각적 경험을 제공할 수 있습니다.

더 자세한 정보는 다음 링크에서 확인할 수 있습니다.

728x90
반응형
LIST