Compose for DesktopでOSのダークモードの設定に合わせてテーマを変更する

先日、KotlinでOSがダークモードに設定されているかどうかを取得する方法を紹介した。

今回は、ダークモードの設定に合わせて、Compose for Desktopのテーマを変更してみる。

ダークモードとライトモードの色設定を作成する。

val DarkGreenColorPalette = darkColors(
    primary = Color.Cyan,
    primaryVariant = Color.Cyan,
    secondary = Color.Cyan,
    background = Color.Black,
    surface = Color.Black,
    onPrimary = Color.Black,
    onSecondary = Color.LightGray,
    onBackground = Color.White,
    onSurface = Color.White,
    error = Color.Red,
)

val LightGreenColorPalette = lightColors(
    primary = Color.Blue,
    primaryVariant = Color.Blue,
    secondary = Color.LightGray,
    background = Color.White,
    surface = Color.White,
    onPrimary = Color.White,
    onSecondary = Color.Gray,
    onBackground = Color.Black,
    onSurface = Color.Black
)

ダークモードかどうかを引数で受け取り、モードによって色設定を変更する。

@Composable
fun MainTheme(isDarkMode: Boolean, content: @Composable () -> Unit) {
    MaterialTheme(content = content, colors = if (isDarkMode) DarkGreenColorPalette else LightGreenColorPalette)
}

現在のモードを取得して、モードにあったテーマを設定する。

@Composable
@Preview
fun App() {
    val detector = OsThemeDetector.getDetector()
    var darkMode: Boolean by remember { mutableStateOf(detector.isDark) }
    val listener: (Boolean) -> Unit = { isDark: Boolean -> darkMode = isDark }
    detector.registerListener(listener)

    MainTheme(isDarkMode = darkMode) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.background)) {
        }
    }
}

全体のコードは以下のようになる。

MainTheme.kt

import androidx.compose.material.MaterialTheme
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

@Composable
fun MainTheme(isDarkMode: Boolean, content: @Composable () -> Unit) {
    MaterialTheme(content = content, colors = if (isDarkMode) DarkGreenColorPalette else LightGreenColorPalette)
}

val DarkGreenColorPalette = darkColors(
    primary = Color.Cyan,
    primaryVariant = Color.Cyan,
    secondary = Color.Cyan,
    background = Color.Black,
    surface = Color.Black,
    onPrimary = Color.Black,
    onSecondary = Color.LightGray,
    onBackground = Color.White,
    onSurface = Color.White,
    error = Color.Red,
)

val LightGreenColorPalette = lightColors(
    primary = Color.Blue,
    primaryVariant = Color.Blue,
    secondary = Color.LightGray,
    background = Color.White,
    surface = Color.White,
    onPrimary = Color.White,
    onSecondary = Color.Gray,
    onBackground = Color.Black,
    onSurface = Color.Black
)

Main.kt

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import com.jthemedetecor.OsThemeDetector

@Composable
@Preview
fun App() {
    val detector = OsThemeDetector.getDetector()
    var darkMode: Boolean by remember { mutableStateOf(detector.isDark) }
    val listener: (Boolean) -> Unit = { isDark: Boolean -> darkMode = isDark }
    detector.registerListener(listener)

    MainTheme(isDarkMode = darkMode) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.background)) {
            Column {
                Text(
                    text = if (darkMode) "Dark Mode" else "Light Mode",
                    color = MaterialTheme.colors.onSurface,
                )
                Button(onClick = { darkMode = !darkMode }) {
                    Text(text = "Switch Mode")
                }
            }
        }
    }
}

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください