To implement a dark mode/light mode theme in an Android app, you can follow these steps. It requires setting up themes for both modes and handling user preferences or system-wide theme changes.
1. Define themes in res/values/themes.xml and res/values-night/themes.xml
res/values/themes.xml (for Light Mode):
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary branding colors. -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryVariant">@color/primaryColorDark</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary colors. -->
<item name="colorSecondary">@color/secondaryColor</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Background and text colors -->
<item name="android:colorBackground">@color/backgroundColorLight</item>
<item name="android:textColor">@color/textColorLight</item>
</style>
</resources>
res/values-night/themes.xml (for Dark Mode):
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme for dark mode. -->
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary branding colors for dark theme -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryVariant">@color/primaryColorDark</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary colors. -->
<item name="colorSecondary">@color/secondaryColor</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Background and text colors -->
<item name="android:colorBackground">@color/backgroundColorDark</item>
<item name="android:textColor">@color/textColorDark</item>
</style>
</resources>
2. Set Colors in res/values/colors.xml and res/values-night/colors.xml
res/values/colors.xml (Light Mode Colors):
<resources>
<color name="primaryColor">#6200EE</color>
<color name="primaryColorDark">#3700B3</color>
<color name="secondaryColor">#03DAC6</color>
<color name="backgroundColorLight">#FFFFFF</color>
<color name="textColorLight">#000000</color>
</resources>
res/values-night/colors.xml (Dark Mode Colors):
<resources>
<color name="primaryColor">#6200EE</color>
<color name="primaryColorDark">#3700B3</color>
<color name="secondaryColor">#03DAC6</color>
<color name="backgroundColorDark">#121212</color>
<color name="textColorDark">#FFFFFF</color>
</resources>
3. Handle Theme Switching in Your Activity
You can set the theme based on the user’s choice or system preference. In Android 10 (API level 29) and higher, you can automatically switch between themes based on the system setting.
In your MainActivity.java or MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set the theme according to system or user preference
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
setContentView(R.layout.activity_main)
}
}
4. Allow User to Toggle Between Dark/Light Mode
To give the user control, you can add a switch or toggle in your settings. For example:
class SettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
val switchTheme = findViewById<SwitchCompat>(R.id.switch_theme)
switchTheme.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}
}
}
5. Persist User Preference
Use SharedPreferences to save and restore the user’s theme choice:
val sharedPref = getSharedPreferences("ThemePref", Context.MODE_PRIVATE)
val editor = sharedPref.edit()
switchTheme.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
editor.putBoolean("darkMode", true)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
editor.putBoolean("darkMode", false)
}
editor.apply()
}
// Restore the user preference
val isDarkMode = sharedPref.getBoolean("darkMode", false)
if (isDarkMode) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
With this implementation, your app will support both dark mode and light mode, while allowing the user to toggle between them or follow the system theme.