Belajar Flutter - Theming & Styling
Episode 7 of 23

Belajar Flutter - Theming & Styling

Episode ini menyulap tampilan aplikasi kalian: ThemeData dan material design theming, custom fonts, colors, dan typography, dukungan dark mode dan adaptive UI, serta styling widget dengan decoration dan responsive design.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Aplikasi yang fungsional belum tentu enak dipakai. Episode 7 menutup celah itu: kalian akan belajar membangun identitas visual yang konsisten lewat theming dan styling. Kita membahas ThemeData dan material design theming, custom fonts, colors, dan typography, dukungan dark mode dan adaptive UI, serta styling widget dengan decoration dan responsive design. Setelah episode ini, aplikasi kalian akan terlihat seperti produk sungguhan, bukan demo.

ThemeData dan Material Design Theming

Menyuntikkan Theme ke Seluruh Aplikasi

Alih-alih mengatur warna di setiap widget, definisikan tema satu kali di MaterialApp:

Theme dengan ColorScheme dari seed color
MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.indigo,
    ),
    useMaterial3: true,
  ),
  home: const HomeScreen(),
)

ColorScheme.fromSeed(seedColor: Colors.indigo) membangkitkan palet warna lengkap dari satu warna benih — pola yang direkomendasikan Material 3. useMaterial3: true mengaktifkan desain token terbaru.

Akses Theme di Seluruh Widget

Mengambil warna dari theme
final colorScheme = Theme.of(context).colorScheme;
 
Container(
  color: colorScheme.primary,
  child: Text(
    'Tombol utama',
    style: TextStyle(color: colorScheme.onPrimary),
  ),
);

Theme.of(context).colorScheme mengambil palet aktif. Dengan pola ini, warna tidak pernah di-hardcode di dalam widget — perubahan tema menyebar otomatis ke seluruh aplikasi.

Custom Fonts, Colors, dan Typography

Mendaftarkan Font di pubspec.yaml

Font custom didaftarkan di pubspec.yaml di bawah blok fonts:

Mendaftarkan font keluarga
flutter:
  fonts:
    - family: Poppins
      fonts:
        - asset: assets/fonts/Poppins-Regular.ttf
        - asset: assets/fonts/Poppins-Bold.ttf
          weight: 700

Setelah font terdaftar di blok flutter.fonts, jalankan flutter pub get lalu pakai keluarga font tersebut.

Mengatur Typography di Theme

Definisikan text theme agar tipografi konsisten:

Text theme kustom
theme: ThemeData(
  textTheme: const TextTheme(
    headlineMedium: TextStyle(
      fontSize: 28,
      fontWeight: FontWeight.bold,
    ),
    bodyMedium: TextStyle(
      fontSize: 16,
      height: 1.5,
    ),
  ),
)

TextTheme mendefinisikan gaya untuk headlineMedium, bodyMedium, dan seterusnya. Seluruh aplikasi memakai gaya ini tanpa harus menulis ulang TextStyle di setiap tempat.

Dark Mode Support dan Adaptive UI

Theme terang dan Gelap Sekaligus

Sediakan dua tema dan Flutter akan memilih berdasarkan setting sistem:

Dark theme otomatis
MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
  ),
  darkTheme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.indigo,
      brightness: Brightness.dark,
    ),
  ),
  home: const HomeScreen(),
)

Dengan theme dan darkTheme terisi, aplikasi menyesuaikan diri dengan mode terang atau gelap perangkat secara otomatis. Brightness.dark membalik palet sehingga tetap kontras.

Mengikuti Platform

Untuk keputusan yang bergantung platform, gunakan Theme.of(context).platform atau MediaQuery:

Responsif terhadap ukuran layar
final lebar = MediaQuery.sizeOf(context).width;
 
if (lebar >= 600) {
  return const WideLayout();
}
return const NarrowLayout();

MediaQuery.sizeOf(context).width membaca lebar layar saat ini. Pola ini adalah dasar responsive design yang akan dibahas mendalam di episode 18.

Styling Widget, Decoration, dan Responsive Design

BoxDecoration untuk Tampilan Kaya

BoxDecoration memberi warna gradasi, border, dan bayangan pada Container:

Kartu dengan dekorasi lengkap
Container(
  width: double.infinity,
  padding: const EdgeInsets.all(16),
  decoration: BoxDecoration(
    gradient: LinearGradient(
      colors: [Colors.indigo, Colors.blue],
    ),
    borderRadius: BorderRadius.circular(12),
    boxShadow: const [
      BoxShadow(
        color: Colors.black26,
        blurRadius: 8,
        offset: Offset(0, 4),
      ),
    ],
  ),
  child: const Text('Kartu bergaya'),
)

BoxShadow memberi kedalaman dan BorderRadius.circular(12) membulatkan sudut. double.infinity membuat Container selebar yang diizinkan parent.

Hindari Hardcode, Pakai Skala

Definisikan konstanta spacing di satu tempat agar konsisten:

Konstanta spacing terpusat
const double spacingKecil = 8;
const double spacingBesar = 24;
 
Padding(
  padding: EdgeInsets.all(spacingKecil),
  child: Text('Elemen dengan jarak konsisten'),
)

EdgeInsets.all(spacingKecil) memakai konstanta yang sama di seluruh aplikasi. Konsistensi spacing dan warna adalah ciri aplikasi yang terlihat profesional.

Penutup

Inti yang harus dibawa pulang:

  • Definisikan tema sekali di MaterialApp dengan ColorScheme.fromSeed.
  • Akses warna lewat Theme.of(context) — jangan hardcode warna di widget.
  • Daftarkan font custom di pubspec.yaml dan atur TextTheme terpusat.
  • Sediakan theme dan darkTheme untuk dukungan dark mode otomatis.
  • BoxDecoration menghidupkan tampilan dengan gradasi, border, dan bayangan.
  • Pusatkan konstanta spacing untuk konsistensi lintas layar.

Di episode 8 selanjutnya kita membahas networking dan data handling — HTTP requests dengan package http atau dio, JSON deserialization dengan dart:convert atau json_serializable, async programming dengan Future dan Stream, serta loading states, error handling, dan retry. Aplikasi kalian mulai terhubung ke dunia luar.