image

26 Feb 2023

9K

35K

Membuat Dark Mode di Aplikasi Flutter: Panduan Lengkap

Dark Mode telah menjadi fitur yang sangat diminati dan bahkan menjadi standar ekspektasi pengguna modern. Selain estetika yang menawan, mode gelap menawarkan berbagai manfaat mulai dari kenyamanan mata di lingkungan minim cahaya hingga penghematan baterai pada perangkat dengan layar OLED. Sebagai pengembang Flutter, mengimplementasikan Dark Mode di aplikasi Anda bukan hanya tentang mengikuti tren, tetapi juga meningkatkan pengalaman pengguna secara signifikan. Artikel ini akan memandu Anda melalui langkah-langkah untuk membuat Dark Mode yang efektif dan profesional di aplikasi Flutter Anda.

Mengapa Dark Mode Penting?

  • Kenyamanan Mata: Mengurangi ketegangan mata, terutama saat menggunakan aplikasi di malam hari atau di lingkungan dengan pencahayaan rendah.
  • Penghematan Baterai: Pada perangkat dengan layar OLED/AMOLED, piksel hitam murni tidak menyala, yang dapat secara signifikan menghemat daya baterai.
  • Aksesibilitas: Dapat membantu pengguna dengan kondisi penglihatan tertentu untuk membaca teks dengan lebih mudah karena kontras yang lebih tinggi.
  • Estetika Modern: Banyak pengguna menyukai tampilan Dark Mode karena terlihat lebih premium dan elegan.

Memahami Sistem Tema Flutter

Flutter, berkat widget MaterialApp, memiliki sistem theming yang kuat dan fleksibel. Inti dari sistem ini adalah kelas ThemeData, yang mendefinisikan tampilan visual aplikasi Anda, seperti skema warna, gaya teks, bentuk widget, dan banyak lagi. Untuk Dark Mode, Flutter menyediakan properti khusus di MaterialApp:

  • theme: Mengatur tema aplikasi untuk mode terang (light mode).
  • darkTheme: Mengatur tema aplikasi untuk mode gelap (dark mode).
  • themeMode: Mengontrol mode tema yang sedang aktif. Properti ini menerima nilai dari enum ThemeMode (system, light, dark).

Implementasi Dasar Dark Mode

Langkah pertama adalah menyiapkan MaterialApp Anda untuk mendukung kedua mode tema. Anda bisa menggunakan ThemeData.light() dan ThemeData.dark() untuk mendapatkan tema standar Material Design:


import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // Secara default, biarkan sistem yang menentukan
  ThemeMode _themeMode = ThemeMode.system;

  void _toggleTheme(ThemeMode mode) {
    setState(() {
      _themeMode = mode;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Aplikasi Dark Mode',
      theme: ThemeData.light(), // Tema untuk mode terang
      darkTheme: ThemeData.dark(), // Tema untuk mode gelap
      themeMode: _themeMode, // Mengontrol mode tema yang aktif
      home: MyHomePage(toggleTheme: _toggleTheme, currentThemeMode: _themeMode),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final Function(ThemeMode) toggleTheme;
  final ThemeMode currentThemeMode;

  MyHomePage({required this.toggleTheme, required this.currentThemeMode});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Aplikasi Dark Mode'),
        actions: [
          IconButton(
            icon: Icon(Icons.light_mode),
            onPressed: () => toggleTheme(ThemeMode.light),
            color: currentThemeMode == ThemeMode.light ? Colors.amber : Colors.white,
          ),
          IconButton(
            icon: Icon(Icons.dark_mode),
            onPressed: () => toggleTheme(ThemeMode.dark),
            color: currentThemeMode == ThemeMode.dark ? Colors.purple : Colors.white,
          ),
          IconButton(
            icon: Icon(Icons.brightness_auto),
            onPressed: () => toggleTheme(ThemeMode.system),
            color: currentThemeMode == ThemeMode.system ? Colors.blue : Colors.white,
          ),
        ],
      ),
      body: Center(
        child: Text(
          'Selamat datang di Dark Mode!',
          style: Theme.of(context).textTheme.headlineMedium,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: Icon(Icons.add),
      ),
    );
  }
}

Dalam contoh di atas, kita menggunakan setState untuk mengubah _themeMode, yang kemudian akan membangun ulang MaterialApp dan menerapkan tema yang sesuai.

Menyesuaikan Tema Gelap Anda

Sangat jarang aplikasi hanya mengandalkan ThemeData.light() dan ThemeData.dark() secara langsung. Anda mungkin ingin menyesuaikan warna, tipografi, atau bentuk widget agar sesuai dengan branding aplikasi Anda. Anda bisa membuat instance ThemeData kustom:


class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.system;

  void _toggleTheme(ThemeMode mode) {
    setState(() {
      _themeMode = mode;
    });
  }

  // Definisi tema terang kustom
  ThemeData _lightTheme = ThemeData(
    primarySwatch: Colors.blue,
    brightness: Brightness.light,
    appBarTheme: AppBarTheme(
      backgroundColor: Colors.blue,
      foregroundColor: Colors.white,
    ),
    textTheme: TextTheme(
      headlineMedium: TextStyle(color: Colors.black87),
      bodyMedium: TextStyle(color: Colors.black54),
    ),
    floatingActionButtonTheme: FloatingActionButtonThemeData(
      backgroundColor: Colors.deepOrange,
      foregroundColor: Colors.white,
    ),
  );

  // Definisi tema gelap kustom
  ThemeData _darkTheme = ThemeData(
    primarySwatch: Colors.indigo,
    brightness: Brightness.dark,
    scaffoldBackgroundColor: Color(0xFF121212), // Warna latar belakang gelap khas
    appBarTheme: AppBarTheme(
      backgroundColor: Color(0xFF1F1F1F),
      foregroundColor: Colors.white,
    ),
    textTheme: TextTheme(
      headlineMedium: TextStyle(color: Colors.white70),
      bodyMedium: TextStyle(color: Colors.white54),
    ),
    floatingActionButtonTheme: FloatingActionButtonThemeData(
      backgroundColor: Colors.teal,
      foregroundColor: Colors.white,
    ),
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Aplikasi Dark Mode Kustom',
      theme: _lightTheme,
      darkTheme: _darkTheme,
      themeMode: _themeMode,
      home: MyHomePage(toggleTheme: _toggleTheme, currentThemeMode: _themeMode),
    );
  }
}

Tips untuk Kustomisasi:

  • ColorScheme: Gunakan ThemeData.from(colorScheme: ...) atau sesuaikan properti colorScheme untuk kontrol granular atas warna-warna dasar Material Design (primary, secondary, surface, background, dll.).
  • copyWith(): Jika Anda ingin memodifikasi tema standar hanya sebagian kecil, gunakan metode copyWith() pada ThemeData.light() atau ThemeData.dark(). Ini akan membuat salinan tema dengan perubahan yang Anda inginkan. Contoh: ThemeData.dark().copyWith(scaffoldBackgroundColor: Colors.black).
  • Warna Semantik: Hindari menggunakan warna hardcoded seperti Colors.white atau Colors.black langsung di widget Anda. Sebaliknya, gunakan properti dari Theme.of(context).colorScheme seperti onSurface, primary, background, dll. Ini akan otomatis menyesuaikan dengan tema yang sedang aktif.

Menyimpan Pilihan Tema Pengguna

Pengguna tentu tidak ingin memilih tema setiap kali mereka membuka aplikasi. Kita perlu menyimpan preferensi tema mereka. Library seperti shared_preferences adalah pilihan yang sangat baik untuk menyimpan data sederhana seperti ini.

  1. Tambahkan dependensi: Tambahkan shared_preferences ke pubspec.yaml Anda.
    
    dependencies:
      flutter:
        sdk: flutter
      shared_preferences: ^2.0.0 # Gunakan versi terbaru
            
  2. Muat dan Simpan Preferensi:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; // Import ini

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.system;

  @override
  void initState() {
    super.initState();
    _loadThemeMode(); // Muat preferensi tema saat aplikasi dimulai
  }

  Future<void> _loadThemeMode() async {
    final prefs = await SharedPreferences.getInstance();
    final String? themeModeString = prefs.getString('themeMode');
    setState(() {
      if (themeModeString == 'light') {
        _themeMode = ThemeMode.light;
      } else if (themeModeString == 'dark') {
        _themeMode = ThemeMode.dark;
      } else {
        _themeMode = ThemeMode.system;
      }
    });
  }

  Future<void> _saveThemeMode(ThemeMode mode) async {
    final prefs = await SharedPreferences.getInstance();
    String themeModeString;
    if (mode == ThemeMode.light) {
      themeModeString = 'light';
    } else if (mode == ThemeMode.dark) {
      themeModeString = 'dark';
    } else {
      themeModeString = 'system';
    }
    await prefs.setString('themeMode', themeModeString);
    setState(() {
      _themeMode = mode;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Aplikasi Dark Mode Persistent',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: _themeMode,
      home: MyHomePage(toggleTheme: _saveThemeMode, currentThemeMode: _themeMode), // Gunakan _saveThemeMode
    );
  }
}
// ... (MyHomePage class tetap sama seperti sebelumnya)

Dengan implementasi ini, preferensi tema pengguna akan dimuat saat aplikasi dimulai dan disimpan setiap kali mereka mengubahnya.

Praktik Terbaik dan Pertimbangan

  • Uji Secara Menyeluruh: Pastikan setiap layar dan widget di aplikasi Anda terlihat baik di kedua mode. Perhatikan kontras teks, ikon, dan elemen UI lainnya.
  • Warna Semantik: Seperti yang disebutkan, gunakan Theme.of(context).colorScheme. Ini memastikan bahwa warna Anda adaptif dan konsisten di seluruh aplikasi.
  • Konsistensi UI/UX: Pastikan transisi antara mode terang dan gelap mulus dan tidak ada elemen yang "menghilang" atau menjadi tidak terbaca.
  • Tinjauan Aksesibilitas: Periksa kontras warna menggunakan alat aksesibilitas untuk memastikan aplikasi Anda ramah bagi semua pengguna.
  • Sediakan Tombol Toggle: Beri pengguna opsi untuk beralih antara Dark Mode, Light Mode, atau mengikuti pengaturan sistem, seperti yang ditunjukkan di contoh.

Kesimpulan

Mengimplementasikan Dark Mode di aplikasi Flutter Anda adalah investasi berharga yang akan meningkatkan pengalaman pengguna dan menunjukkan perhatian terhadap detail. Dengan sistem theming Flutter yang fleksibel dan alat bantu seperti shared_preferences, Anda dapat dengan mudah membuat aplikasi yang adaptif dan menawan di kedua mode. Mulailah bereksperimen dengan tema kustom Anda sendiri dan buat aplikasi Flutter Anda bersinar—baik dalam terang maupun gelap!

Related Articles

Nov 21, 2025

Membangun Aplikasi Flutter yang Efisien dengan State Management Provider

Membangun Aplikasi Flutter yang Efisien dengan State Management Provider Flutter telah merevolusi pengembangan aplikasi mobile dengan kemampuannya untuk memban

Nov 21, 2025

Tips Optimasi Performa Flutter untuk Aplikasi Mobile

Tips Optimasi Performa Flutter untuk Aplikasi Mobile Performa adalah salah satu faktor krusial yang menentukan keberhasilan dan pengalaman pengguna dalam aplik

Nov 22, 2025

Integrasi API REST di Flutter: Pendekatan Modern dengan Dio dan Provider

Integrasi API REST di Flutter: Pendekatan Modern dengan Dio dan Provider Dalam pengembangan aplikasi modern, kemampuan untuk berinteraksi dengan layanan backen