Gyakori a mobil- és web alkalmazásokban is a dark, azaz sötét és világos mód (mode) közötti váltás. Ezt egy alternatív, dark theme megvalósításával tudjuk lehetővé tenni.
Megvalósítás
Ehhez létre kell hozni egy másik színsémát.
var kDarkColorScheme = ColorScheme.fromSeed(seedColor: seedColor);
A seedColor-nak valami sötétebb színt választunk:
var kDarkColorScheme = ColorScheme.fromSeed(
seedColor: Color.fromARGB(255, 5, 99, 125),
);
És ez után létre tudjuk hozni a sötét témát is. Ami eddig témánk volt az a világos téma:
MaterialApp(
theme: ThemeData().copyWith(
És emellé létre tudjuk hozni a sötétet is:
MaterialApp(
darkTheme: ,
A MaterialApp-nak van egy másik, ún. darkTheme nevű tulajdonsága is a sötét módhoz. És ezt pedig szintén a ThemeData-val tudjuk létrehozni, aminek a dark() konstruktorát meghívva kapunk egy sor alapértelmezett dark mode beállítást és konfigurációt:
darkTheme: ThemeData.dark(),
Ezzel nem kell mindent külön-külön kézzel beállítani, csupán talán ennyit:
darkTheme: ThemeData.dark().copyWith(
useMaterial3: true,
colorScheme: kDarkColorScheme,
),
Sötét mód bekapcsolása
Ezt a MaterialApp-nak a themeMode tulajdonságával lehet vezérelni, ami egy ThemeMode objektumot vár:
themeMode: Thememode
vannak előre beállított ThemeMode értékek:
Ha a ThemeMode.dark vagy a ThemeMode.light értéket választjuk, akkor ezzel azt mondjuk az appnak, hogy állandóan dark- vagy light módban fusson, mindegy a user mit állít be a telón keresztül.
Ha viszont a ThemeMode.system-et választjuk, akkor az app azt a módot használja, amit a user a telóban beállított:
themeMode: ThemeMode.system
Ez egyébként az alapértelmezett beállítás, szóval nem is kell külön megadni.
A kijelző módot például Samsung telón így tudtam beállítani:
Hiba kezelése mód váltáskor
Ha kapunk egy ilyen null értékes üzenetet:
Akkor az azért lehet, mert valahol a stílus null értéket várt, de mi a ” ! ” jellel kikényszerítettük, hogy a Flutter ne jelezzen hibát:
horizontal: Theme.of(context).cardTheme.margin!.horizontal,
Pontosabban feltételeztük, hogy nem lesz null. Márpedig most az lett.
A hibát tudjuk javítani, hogy a kérdéses részt a téma beállításánál lemásoljuk és a dark témához is megadjuk, illetve átírjuk benne a színsémát a sötétre (kDarkColorScheme):
darkTheme: ThemeData.dark().copyWith(
useMaterial3: true,
colorScheme: kDarkColorScheme,
cardTheme: const CardTheme().copyWith(
color: kDarkColorScheme.secondaryContainer,
margin: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
),
),
És ez után már nem jelentkezik a hiba, látjuk a sötét módot, bár még nem az igazi, de működik:
Egyébként ez azért is van így, mert a színséma, bár a seedColor alapján lett generálva, de a különféle árnyalatok és egyéb színvariánsok azok a világos témához vannak optimalizálva.
Szerencsére ezt a seedColor konstrukoron belül a brightness tulajdonsággal meg tudjuk mondani a Flutternek, hogy mindent a dark módhoz optimalizáljon:
var kDarkColorScheme = ColorScheme.fromSeed(
brightness: Brightness.dark,
seedColor: const Color.fromARGB(255, 5, 99, 125),
);
És most már teljesen másképp néz ki:
Még egy utolsó megjegyzés: Amikor a user visszaállítja a telefonon belül a light módot, akkor az alkalmazás ezt azonnal követni fogja.
Dark / Light mód lekérdezés
final isDarkMode =
MediaQuery.of(context).platformBrightness == Brightness.dark;
A MediaQuery-nek van egy of() konstruktora, ami a context objektumot várja inputként.