themedarkmodepengaturanMahir4 mnt baca

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:

dart
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:

dart
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: ThemeMode hanya memilih antara theme dan darkTheme yang sudah kamu definisikan; ia tidak membuat dark mode otomatis dari tema terang. Kalau kamu lupa mengisi darkTheme, ThemeMode.dark akan 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.