Theme dan ThemeData — mekanisme utama tema di Flutter yang memungkinkan pengaturan warna, font, jarak, dan gaya komponen secara global untuk seluruh aplikasi. ThemeData adalah objek konfigurasi yang diteruskan ke MaterialApp melalui parameter theme. Menurut dokumentasi resmi Flutter (2026), konfigurasi ThemeData yang benar mengurangi jumlah kode gaya yang berulang hingga 70–80% dan memastikan tampilan layar yang seragam. Sistem pewarisan bawaan memungkinkan penggantian tema pada tingkat widget individu melalui Theme.of(context).
Poin utama
ThemeData — kelas yang berisi deskripsi lengkap gaya visual aplikasi Material. Diteruskan ke MaterialApp melalui parameter theme atau darkTheme dan diwarisi oleh semua widget turunan. Setiap widget Material Design menggunakan ThemeData untuk mendapatkan gayanya: warna tombol, ukuran AppBar, gaya teks, jarak kartu, dan ikon.
Di dasar ThemeData terdapat ColorScheme, yang mendefinisikan warna primary, secondary, surface, error, dan warna lainnya. Dari warna-warna ini, status (hover, focus, pressed) untuk semua komponen Material dihitung secara otomatis. Misalnya, ElevatedButton menggunakan warna primary untuk latar belakang dan onPrimary untuk teks — tanpa konfigurasi tambahan.
Widget Theme — adalah InheritedWidget yang menyebarkan tema ke bawah pohon widget. Widget apa pun dapat memperoleh tema saat ini melalui Theme.of(context), serta membuat tema baru berdasarkan tema yang ada dengan nilai yang diganti melalui Theme.copyWith atau ThemeData.copyWith.
Kesimpulan: ThemeData — sumber gaya tunggal aplikasi. Mulailah pengembangan dengan mendefinisikan ThemeData — ini menetapkan bahasa visual seluruh proyek dan mencegah gaya yang tersebar di berbagai layar.
ColorScheme — elemen utama tema di Material 3. Ini menggantikan primarySwatch dan primaryColor yang sudah usang, menyediakan rangkaian warna lengkap untuk semua status dan komponen.
ColorScheme berisi 12 warna dasar: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline, dan shadow. Untuk setiap warna, varian light dan dark dihitung secara otomatis, serta warna untuk status hover, focus, pressed, dan dragged. Saat hanya menentukan primary, framework menghasilkan sisa warna secara otomatis melalui ColorScheme.fromSeed.
Metode ColorScheme.fromSeed (Material 3) menerima satu warna dasar seedColor dan menghasilkan palet harmonis lengkap berdasarkan algoritma Material Design 3. Ini menghilangkan pemilihan manual warna complementary dan analogous. Cukup dengan memberikan satu warna merek utama, dan ColorScheme.fromSeed akan membuat palet yang koheren untuk seluruh sistem Material.
Kesimpulan: di proyek baru gunakan ColorScheme.fromSeed untuk menghasilkan palet. Untuk kompatibilitas Material 2 — primarySwatch. ColorScheme adalah minimum wajib untuk Material 3.
TextTheme — bagian dari ThemeData yang mendefinisikan gaya teks untuk semua tingkat judul, subjudul, body, dan label. Material Design mendefinisikan 15 gaya teks: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium, dan lainnya.
Tipografi diatur baik melalui GoogleFonts untuk pemuatan font otomatis, atau melalui Theme.of(context).textTheme bawaan dengan TextStyle kustom. GoogleFonts menyediakan ratusan font melalui paket google_fonts, yang menyimpannya di cache lokal setelah pemuatan pertama. Alternatif — menyematkan font ke dalam aset proyek melalui pubspec.yaml.
Untuk tipografi adaptif, TextTheme mendukung MediaQuery.textScaleFactor — saat font sistem diperbesar, semua gaya teks diskalakan secara proporsional. Selain itu, ukuran font yang berbeda dapat diatur untuk faktor bentuk yang berbeda melalui isTest tergantung pada MediaQuery.size.width.
Kesimpulan: definisikan TextTheme di ThemeData dan gunakan Theme.of(context).textTheme untuk semua elemen teks. Ini memastikan keseragaman font dan menyederhanakan perubahan global pada tipografi.
Theme — InheritedWidget yang menyebarkan tema dari induk ke anak. Setiap widget turunan dapat membaca tema saat ini melalui Theme.of(context) dan juga membuat salinannya sendiri dengan perubahan melalui ThemeData.copyWith.
Mekanisme pewarisan: jika widget dibungkus dalam Theme dengan data baru, semua turunannya melihat tema yang diganti, sedangkan widget di luar bungkusan ini melihat tema asli. Ini memungkinkan, misalnya, mengisolasi gaya untuk layar tertentu: judul menggunakan tema kustom dengan AppBarTheme yang diubah, dan seluruh aplikasi menggunakan tema standar.
Penumpukan Theme bisa tidak terbatas. Flutter menggunakan pencarian hierarkis: saat memanggil Theme.of(context), framework naik ke atas pohon hingga Theme pertama dan mengembalikan temanya. Jika tidak ada Theme yang ditemukan — pengecualian dilemparkan. Oleh karena itu, MaterialApp selalu membungkus aplikasi dalam Theme.
Kesimpulan: pewarisan Theme — mekanisme fleksibel untuk mengisolasi gaya. Gunakan penggantian tema untuk layar individu tanpa menduplikasi konfigurasi umum.
Dark theme — kemampuan bawaan Flutter untuk beralih antara tema terang dan gelap. ThemeData disimpan dalam parameter theme (terang) dan darkTheme (gelap) dari MaterialApp. Parameter themeMode mengelola mode: ThemeMode.light (selalu terang), ThemeMode.dark (selalu gelap), atau ThemeMode.system (mengikuti pengaturan sistem).
Saat mengimplementasikan tema gelap, tidak perlu membuat semua gaya dari awal. Cukup dengan memberikan ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) di darkTheme. Framework secara otomatis menyesuaikan warna untuk latar belakang gelap: surface menjadi abu-abu gelap, teks menjadi terang. Subtema lainnya (AppBarTheme, CardTheme, BottomNavigationBarTheme) diwarisi dari versi terang, kecuali jika diganti secara eksplisit.
Untuk transisi mulus antar tema, Flutter menyediakan animasi melalui AnimatedTheme. Saat themeMode berubah, warna dan gaya dianimasikan, menciptakan peralihan yang menyenangkan secara visual. AnimatedTheme menggunakan Duration dan Curve untuk mengatur kecepatan animasi.
Kesimpulan: dark theme diimplementasikan melalui darkTheme dan ColorScheme.fromSeed dengan brightness: Brightness.dark. Gunakan ThemeMode.system untuk mengikuti pengaturan sistem pengguna.
Contoh 1 — konfigurasi tema global melalui MaterialApp menggunakan ColorScheme.fromSeed.
final ThemeData appTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.indigo,
brightness: Brightness.light,
),
appBarTheme: const AppBarTheme(
centerTitle: true,
elevation: 0,
),
cardTheme: const CardTheme(
elevation: 2,
margin: EdgeInsets.all(8),
),
);
return MaterialApp(
theme: appTheme,
themeMode: ThemeMode.system,
home: const MyHomePage(),
);
Dalam contoh ini, ThemeData dibuat dengan Material 3, skema warna berbasis indigo, dan gaya AppBar dan Card kustom. useMaterial3 mengaktifkan sistem tema Material 3 yang baru, dan ColorScheme.fromSeed menghasilkan palet lengkap.
Contoh 2 — akses ke tema dan penggantian untuk sebagian aplikasi.
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Text(
'Judul standar',
style: theme.textTheme.headlineMedium,
),
Theme(
data: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.orange,
),
),
child: const SpecialSection(),
),
],
);
}
Contoh kedua menunjukkan penggunaan Theme.of(context) untuk membaca gaya dan Theme() dengan copyWith untuk mengganti tema di bagian pohon tanpa mengubah konfigurasi global. SpecialSection di dalam Theme akan mendapatkan warna primary oranye, sisa aplikasi mempertahankan indigo asli.
Kesimpulan: tema global diatur di MaterialApp, akses melalui Theme.of(context), penggantian melalui Theme dengan copyWith. Untuk Material 3 gunakan ColorScheme.fromSeed.
Kesalahan 1: menggunakan primarySwatch alih-alih ColorScheme di Material 3. primarySwatch sudah usang dan tidak didukung di Material 3. Saat menggunakan useMaterial3: true dengan primarySwatch, Flutter mengeluarkan peringatan. Solusi: beralih ke ColorScheme.fromSeed untuk menghasilkan palet.
Kesalahan 2: mengatur warna secara kaku di widget alih-alih menggunakan Theme.of(context). Pengembang menulis Colors.blue langsung di Container, bukan warna primary atau secondary dari tema. Saat tema berubah, warna-warna ini tetap tidak berubah, melanggar gaya seragam. Solusi: selalu gunakan Theme.of(context).colorScheme.primary atau warna lain dari tema.
Kesalahan 3: tidak adanya darkTheme. Jika aplikasi tidak mendefinisikan darkTheme, saat tema gelap diaktifkan di perangkat, Flutter mencoba menyesuaikan tema terang secara otomatis, yang sering memberikan hasil berkualitas rendah. Solusi: selalu berikan darkTheme di MaterialApp, bahkan jika tema gelap bukan prioritas — ini adalah UX penting bagi pengguna.
Kesalahan 4: membuat tema baru setiap build. Jika ThemeData dibuat di dalam metode build, setiap pembangunan ulang widget membuat objek tema baru, merusak optimasi InheritedWidget. Solusi: pindahkan ThemeData ke bidang statis atau konstruktor const di luar build.
Kesimpulan: tema yang benar memerlukan pendekatan terpusat yang seragam. Pindahkan ThemeData ke konstanta, gunakan skema warna dari tema, dan selalu definisikan kedua tema — terang dan gelap.
Pertanyaan yang Sering Diajukan
ThemeData — data konfigurasi (warna, font, gaya). Theme — InheritedWidget yang meneruskan ThemeData ke bawah pohon widget. Theme.of(context) mengembalikan ThemeData yang disebarkan oleh Theme terdekat dalam konteks saat ini.
Kelola themeMode di MaterialApp melalui status aplikasi. Ubah status dari ThemeMode.light ke ThemeMode.dark, dan Flutter akan membangun ulang seluruh pohon dengan tema baru. Untuk animasi halus gunakan AnimatedTheme.
ColorScheme.fromSeed — metode Material 3 yang menerima satu warna dasar (seedColor) dan menghasilkan palet harmonis lengkap: primary, secondary, tertiary, surface, error, dan varian on-nya. Memungkinkan mendapatkan skema warna yang koheren dari satu warna merek.
Melalui TextTheme di dalam ThemeData: tentukan TextStyle dengan fontFamily untuk setiap tingkat. Untuk Google Fonts gunakan paket google_fonts, berikan fontFamily langsung ke TextTheme. Untuk font lokal — hubungkan melalui pubspec.yaml di bagian fonts.
Ya. Bungkus layar dalam Theme dengan data yang diganti melalui copyWith. Semua widget turunan di dalam Theme ini akan mendapatkan gaya yang dimodifikasi, sedangkan seluruh aplikasi mempertahankan tema asli. Ini tidak menciptakan overhead tambahan.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga