Détecteur de mode sombre
Détectez le mode sombre du système d'exploitation depuis Kotlin et recomposez votre interface Compose quand le thème change.
darkmode-detector indique si le système d'exploitation est en mode sombre et vous prévient
lorsque cela change. Il fournit un composable isSystemInDarkMode() qui recompose aux
changements de thème, ainsi qu'une API impérative IDarkModeDetector utilisable hors de Compose.
macOS, Windows et Linux sont pris en charge.
Ajouter la dépendance
dependencies {
implementation("dev.nucleusframework:nucleus.darkmode-detector:2.4.3")
}Détecter le mode sombre dans Compose
Appelez isSystemInDarkMode() et utilisez le résultat pour choisir votre palette de couleurs. Le
composable recompose quand le thème système change :
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import dev.nucleusframework.darkmodedetector.isSystemInDarkMode
@Composable
fun App() {
val isDark = isSystemInDarkMode()
MaterialTheme(
colorScheme = if (isDark) darkColorScheme() else lightColorScheme(),
) {
// Le contenu recompose quand le thème de l'OS bascule.
}
}Le isSystemInDarkTheme() de Compose Desktop ne lit que LocalSystemTheme, dont le défaut est
un snapshot Skiko non réactif — il ne se met pas à jour quand l'utilisateur change de thème à
l'exécution. isSystemInDarkMode() renvoie la valeur courante et enregistre un listener qui
déclenche une recomposition à chaque changement.
Pont vers Compose isSystemInDarkTheme
Depuis 2.3, nucleusApplication fournit le LocalSystemTheme de Compose à partir de
isSystemInDarkMode() sur les points d'entrée AWT et Tao (les fenêtres Tao l'héritent via le
pont de locals de scène). L'isSystemInDarkTheme() officiel d'AndroidX — et toute bibliothèque
qui l'appelle — suit alors les changements de thème OS sous le DSL, sans appeler les API Nucleus
à chaque call site.
darkmode-detector est une dépendance api de nucleus-application, donc le détecteur est
sur le classpath consommateur dès que vous utilisez le point d'entrée application. Ajoutez encore
la coordonnée explicitement si vous utilisez le détecteur hors de nucleusApplication.
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import dev.nucleusframework.application.nucleusApplication
fun main() = nucleusApplication {
// isSystemInDarkTheme() recompose quand le thème OS bascule
val dark = isSystemInDarkTheme()
MaterialTheme(colorScheme = if (dark) darkColorScheme() else lightColorScheme()) {
DecoratedWindow(onCloseRequest = ::exitApplication) { /* … */ }
}
}Utilisez isSystemInDarkMode() hors de Compose ou hors de nucleusApplication. Préférez
isSystemInDarkTheme() pour Material stock / les composables tiers qui en dépendent déjà.
Dans un @Preview (quand LocalInspectionMode vaut true), isSystemInDarkMode() délègue au
isSystemInDarkTheme() de Compose, pour que les previews s'affichent sans détecteur actif.
Fonctionnement
Chaque plateforme lit le thème système via un pont natif JNI et surveille les changements de l'OS. Aucun polling n'est utilisé : le détecteur réagit aux notifications de changement émises par l'OS lui-même.
- macOS : lit la préférence système
AppleInterfaceStyleet enregistre un observateur viaNSDistributedNotificationCenter. - Windows : lit la valeur de registre
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightThemeet la surveille avecRegNotifyChangeKeyValuesur un thread natif en arrière-plan. - Linux : lit la préférence
color-schemedu portail XDG Desktop via l'interface D-Busorg.freedesktop.portal.Settings; la valeur1signifie prefer-dark.
Sur les plateformes non prises en charge, getPlatformDarkModeDetector() renvoie
NoopDarkModeDetector, qui rapporte toujours le mode clair et ignore les listeners.
Référence de l'API
Lire le thème courant
getPlatformDarkModeDetector() renvoie l'IDarkModeDetector de la plateforme courante. Appelez
isDark() pour une lecture ponctuelle :
import dev.nucleusframework.darkmodedetector.getPlatformDarkModeDetector
val detector = getPlatformDarkModeDetector()
val dark: Boolean = detector.isDark()Écouter les changements
Enregistrez un java.util.function.Consumer<Boolean> pour être notifié quand le thème change, et
retirez-le quand vous n'en avez plus besoin :
import dev.nucleusframework.darkmodedetector.getPlatformDarkModeDetector
import java.util.function.Consumer
val detector = getPlatformDarkModeDetector()
val listener = Consumer<Boolean> { isDark ->
println("mode sombre : $isDark")
}
detector.registerListener(listener)
// Plus tard, arrêtez de recevoir les mises à jour.
detector.removeListener(listener)L'interface complète :
interface IDarkModeDetector {
fun isDark(): Boolean
fun registerListener(listener: Consumer<Boolean>)
fun removeListener(listener: Consumer<Boolean>)
}Utiliser un détecteur no-op
NoopDarkModeDetector implémente IDarkModeDetector sans toucher à l'OS. isDark() renvoie
toujours false et les listeners sont ignorés — pratique pour les tests ou les environnements
headless :
import dev.nucleusframework.darkmodedetector.IDarkModeDetector
import dev.nucleusframework.darkmodedetector.NoopDarkModeDetector
val detector: IDarkModeDetector = NoopDarkModeDetectorEt ensuite
- Couleurs système — lisez la couleur d'accentuation du système et l'état contraste élevé.
- Infos système — interrogez l'OS, le CPU, la mémoire et la batterie depuis Kotlin.
- Intégration OS — le reste des API du système d'exploitation.
Contrôles média
Publiez les métadonnées de lecture dans le centre média système et gérez les commandes de lecture sur macOS, Windows et Linux depuis Kotlin.
Couleur d'accent système
Lisez la couleur d'accent de l'OS et le réglage haut contraste choisis par l'utilisateur sous forme d'état Compose réactif.