Jetpack Compose is a new UI toolkit from Google that is used to create native Android UI. It speeds up and simplifies UI development by using less code, Kotlin APIs, and powerful tools.
Fortunately, Android 10 and later enable automatically "dark-theming" your app by forcing it to utilize certain darker hues. You may enable this system feature for your app by adding the
android:forceDarkAllowed="true"To the theme of your choice. When this option is enabled, it will automatically evaluate your light theme and apply a dark version to it.
Now there are two problems with the above approach :
- What if the user wants dark mode for a specific app and not system-wide dark mode?
- How to implement seamless dark mode below android 10 using jetpack compose?
So now we will write a template that will help us enable dark mode on lower versions of android and also if the user wants to enable it for a specific app.
Steps to Implement Dark Mode
Step 1: Create a new android studio project
To create a new project in the Android Studio, please refer to How to Create a new Project in Android Studio with Jetpack Compose.
Step 2: Working with MainActivity.kt
Navigate to app > kotlin+java > {package-name} > MainActivity.kt and add the following code. In this file, we will be creating a custom theme and a switch to toggle between light and dark mode with respect to the custom theme.
MainActivity.kt:
package com.geeksforgeeks.demo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val isDarkMode = remember { mutableStateOf(false) }
MyCustomTheme(isDarkMode) {
MyCustomScreen(isDarkMode)
}
}
}
}
@Composable
fun MyCustomTheme(isDarkMode: MutableState<Boolean>, content: @Composable () -> Unit) {
val darkColors = darkColorScheme(
primary = Color(0xFF00C853),
onPrimary = Color.Black,
background = Color(0xFF121212),
onBackground = Color.White,
surface = Color(0xFF121212),
onSurface = Color.White
)
val lightColors = lightColorScheme(
primary = Color(0xFF00C853),
onPrimary = Color.White,
background = Color.White,
onBackground = Color.Black,
surface = Color.White,
onSurface = Color.Black
)
val colors = if (isDarkMode.value) darkColors else lightColors
MaterialTheme(colorScheme = colors) {
Surface(
modifier = Modifier.fillMaxSize(),
color = colors.background
) {
content()
}
}
}
@Composable
fun MyCustomScreen(isDarkMode: MutableState<Boolean>) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Switch(
checked = isDarkMode.value,
onCheckedChange = { isDarkMode.value = it }
)
Text(
text = if (isDarkMode.value) "Dark Mode" else "Light Mode",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(top = 8.dp)
)
}
}