Dark Mode Toggle
Mode gelap: darkTheme, ThemeMode, dan switch pengaturan.
Kenapa Dark Mode Lebih dari Sekadar Warna
Dark mode bukan tren kosmetik. Ia mengurangi ketegangan mata saat aplikasi dipakai malam hari (kasir warung yang buka sampai larut, misalnya), menghemat baterai di layar AMOLED karena piksel hitam benar-benar mati, dan kini sudah jadi ekspektasi standar: user Android dan iOS bisa mengatur mode gelap di level sistem dan berharap aplikasi mengikutinya. Flutter mendukung ini secara native lewat tiga properti MaterialApp: theme, darkTheme, dan themeMode. Karena widget-mu sudah memakai Theme.of(context) (modul sebelumnya), seluruh aplikasi bisa berganti mode tanpa mengubah satu pun layar.
Dua Tema + ThemeMode
Pola dasarnya sederhana, simpan pilihan user di state:
class _MyAppState extends State<MyApp> {
ThemeMode _mode = ThemeMode.system;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
),
),
themeMode: _mode,
home: PengaturanPage(
mode: _mode,
onModeChanged: (m) => setState(() => _mode = m),
),
);
}
}ThemeMode.system mengikuti pengaturan HP dan merupakan default terbaik untuk user baru: aplikasi langsung terasa native tanpa user menyentuh apa pun.
Kasus Nyata: Pilihan Tersimpan
Aplikasi produksi butuh tiga pilihan (Terang, Gelap, Ikuti Sistem) dan pilihan itu harus bertahan setelah aplikasi ditutup. Simpan memakai shared_preferences:
enum PilihanTema { terang, gelap, sistem }
class PengaturanPage extends StatelessWidget {
final PilihanTema mode;
final ValueChanged<PilihanTema> onModeChanged;
const PengaturanPage({
super.key,
required this.mode,
required this.onModeChanged,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Tampilan')),
body: ListView(
children: [
RadioListTile<PilihanTema>(
title: const Text('Terang'),
value: PilihanTema.terang,
groupValue: mode,
onChanged: (v) => onModeChanged(v!),
),
RadioListTile<PilihanTema>(
title: const Text('Gelap'),
value: PilihanTema.gelap,
groupValue: mode,
onChanged: (v) => onModeChanged(v!),
),
RadioListTile<PilihanTema>(
title: const Text('Ikuti sistem'),
value: PilihanTema.sistem,
groupValue: mode,
onChanged: (v) => onModeChanged(v!),
),
],
),
);
}
}Di MyApp, baca preferensi tersimpan sekali saat startup (tampilkan splash/loading sampai selesai dibaca), lalu petakan enum ke ThemeMode.light, ThemeMode.dark, atau ThemeMode.system, dan tulis kembali setiap kali user mengganti.
Edge Cases yang Sering Terlewat
Pertama, ada jeda antara aplikasi dibuka dan preferensi selesai dibaca dari disk. Kalau themeMode default-nya light lalu tiba-tiba jadi dark, user melihat kedipan (flash). Solusinya: tahan di layar splash sampai preferensi terbaca, atau default-kan ke ThemeMode.system yang hampir selalu benar. Kedua, ikon status bar: di mode gelap, AppBar terang dengan ikon gelap bisa tidak terbaca kalau kamu mengoverride warna manual; biarkan AppBarTheme bawaan yang mengatur systemOverlayStyle. Ketiga, gambar dan ilustrasi: logo dengan background putih akan terlihat seperti tempelan kotak di dark mode, siapkan varian gelap atau pakai gambar transparan (PNG/SVG). Keempat, jangan lupa menguji SEMUA layar di kedua mode; bug klasik adalah teks yang hardcode Colors.black sehingga hilang di atas background gelap.
Kapan TIDAK Perlu Toggle Manual
Kalau aplikasimu sederhana dan tidak punya halaman pengaturan, cukup set themeMode: ThemeMode.system dan sediakan darkTheme yang rapi. Menambah halaman pengaturan hanya demi satu switch adalah over-engineering. Toggle manual baru layak saat user memang meminta kontrol eksplisit, misalnya aplikasi kasir yang dipakai di bawah lampu terang warung dan user ingin memaksa mode terang walau HP-nya dark mode.
Catatan teknis:
ThemeModehanya memilih antarathemedandarkThemeyang sudah kamu definisikan; ia tidak membuat dark mode otomatis dari tema terang. Kalau kamu lupa mengisidarkTheme,ThemeMode.darkakan jatuh ke tema terang dan user mengira fiturnya rusak.
Tantangan
Switch dark mode
Lengkapi: MaterialApp dengan theme + darkTheme, dan SwitchListTile 'Mode Gelap' yang mengubah themeMode via setState.