Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
Dizi · 16/61 Flutter Türkçe Tutorial
- Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
- Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
- Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
- Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
- Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
- Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
- Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
- Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
- Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
- Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
- Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
- Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
- Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
- Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
- Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
- Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
- Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
- Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
- Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
- Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
- Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
- Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
- Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
- Bölüm 6 — Konu 24: Provider Paketi
- Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
- Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
- Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
- Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
- Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
- Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
- Bölüm 7 — Konu 31: Deep Linking
- Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
- Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
- Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
- Bölüm 8 — Konu 35: Implicit Animasyonlar
- Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
- Bölüm 8 — Konu 37: Hero Animasyonları
- Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
- Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
- Bölüm 9 — Konu 40: Platform Channels
- Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
- Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
- Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
- Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
- Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
- Bölüm 10 — Konu 46: CI/CD
- Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
- Bölüm 10 — Konu 48: DevTools Profiling
- Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
- Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
- Bölüm 11 — Konu 51: Supabase Alternatifi
- Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
- Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
- Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
- Bölüm 12 — Konu 55: Flutter Web / Desktop
- Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
- Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
- Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
- Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
- Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
- Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
İçindekiler 9 başlık
- Neden Tema Sistemi Var?
- ThemeData — Uygulama Genelinde Stil Tanımlama
- Theme.of(context) — Temaya Erişim
- ColorScheme — Modern Renk Yönetimi
- Karanlık Mod (Dark Mode) Desteği
- Elle Tema Değiştirme — StatefulWidget ile
- Widget Seviyesinde Tema Geçersiz Kılma (Override)
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
Neden Tema Sistemi Var?
Şimdiye kadar, her widget'a renk/font/stil tek tek verdik (TextStyle(color: Colors.blue) gibi). Bu, küçük örnekler için sorun değil, ama gerçek bir uygulamada tutarlılığı korumak çok zorlaşır — 50 farklı ekranda "ana renk"i değiştirmek istediğinde, hepsini tek tek bulup değiştirmen gerekir. Tema sistemi, bunu merkezi bir yerden yönetmeni sağlar.
ThemeData — Uygulama Genelinde Stil Tanımlama
Bölüm 3 Konu 10'da MaterialApp'in theme: parametresini kısaca görmüştük — şimdi derinlemesine işleyelim:
MaterialApp(
theme: ThemeData(
primaryColor: Colors.indigo,
scaffoldBackgroundColor: Colors.grey[100],
textTheme: TextTheme(
headlineMedium: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(fontSize: 16),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
),
),
),
home: AnaEkran(),
)ThemeData, Dart Bölüm 6'da öğrendiğimiz class'lar ve named parametreler kullanılarak tasarlanmış, devasa bir yapılandırma nesnesidir — düzinelerce widget türü için (butonlar, metin alanları, kartlar, vb.) varsayılan stiller tanımlamanı sağlar.
Theme.of(context) — Temaya Erişim
Bölüm 1 Konu 4'te (hot reload deneyinde) Theme.of(context).textTheme.headlineMedium kullanmıştık — şimdi bunun nasıl çalıştığını anlayalım:
Text(
'Başlık',
style: Theme.of(context).textTheme.headlineMedium,
)Theme.of(context) ne yapıyor? Bu, Bölüm 2 Konu 5'te "context'i şimdilik bir bilgi taşıyıcı olarak düşün" dediğimiz noktanın gerçek gücünü gösteriyor. BuildContext, widget'ın ağaçtaki konumunu bildiği için, Theme.of(context), "bu widget'ın en yakın üst ebeveyninde tanımlı olan ThemeData'yı bul" işlemini yapar. Bu, Dart Bölüm 7'de öğrendiğimiz kalıtım zincirini andıran, ama widget ağacı üzerinde çalışan bir mekanizma — "en yakın atadaki ayarı devral" mantığı.
Neden bu şekilde tasarlandı, neden global bir değişken kullanılmadı? Bölüm 8'de (Flutter müfredatı, InheritedWidget konusunda) bunun tam mekanizmasını göreceğiz — ama şimdiden bil ki, Theme.of(context)'in kendisi de bir InheritedWidget kullanır. Bu, "widget ağacı boyunca veri paylaşmanın" Flutter'daki temel yöntemidir.
ColorScheme — Modern Renk Yönetimi
Material Design 3 ile birlikte, tek tek renkler (primaryColor gibi) yerine, bütünsel bir renk sistemi olan ColorScheme öne çıktı:
ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
),
)ColorScheme.fromSeed() — bu, tek bir "tohum" (seed) renkten, Material Design'ın renk teorisi kurallarına göre, uyumlu bir renk paleti (birincil, ikincil, arka plan, hata rengi gibi düzinelerce renk) otomatik olarak üretir. Bu, elle her rengi tek tek tanımlamak yerine, tek bir karar (ana renk) ile tutarlı bir tasarım sistemi elde etmeni sağlar.
Container(
color: Theme.of(context).colorScheme.primary,
child: Text(
'Merhaba',
style: TextStyle(color: Theme.of(context).colorScheme.onPrimary),
),
)primary ve onPrimary ayrımı önemli: primary, ana rengi; onPrimary, o rengin üzerine yazılacak metnin rengini belirtir (genelde kontrast için beyaz/siyah). Bu isimlendirme kalıbı (on öneki), ColorScheme'in her rengi için geçerlidir (secondary/onSecondary, error/onError gibi) — Dart Bölüm 1'de öğrendiğimiz tutarlı isimlendirme prensibinin, Flutter'ın kendi API tasarımında uygulanmış hali.
Karanlık Mod (Dark Mode) Desteği
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.light),
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark),
),
themeMode: ThemeMode.system, // sistem ayarına göre otomatik seç
home: AnaEkran(),
)themeMode: ThemeMode.system, Dart Bölüm 7'de öğrendiğimiz enum'a benzer bir yapı kullanır (ThemeMode, system/light/dark değerlerine sahip bir enum) — cihazın sistem ayarına (kullanıcının telefonunda karanlık mod açık mı) göre, Flutter otomatik olarak theme veya darkTheme'i seçer.
Elle Tema Değiştirme — StatefulWidget ile
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThemeMode _temaModu = ThemeMode.system;
void _temaDegistir(bool karanlikMi) {
setState(() {
_temaModu = karanlikMi ? ThemeMode.dark : ThemeMode.light;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)),
darkTheme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark)),
themeMode: _temaModu,
home: AnaEkran(onTemaDegistir: _temaDegistir),
);
}
}Bu, Bölüm 2 Konu 6'da öğrendiğimiz setState() mekanizmasını, tema bağlamında kullanıyor — _temaModu değiştiğinde, setState() tetikleniyor ve MaterialApp (ve altındaki tüm widget ağacı) yeni temaya göre yeniden çiziliyor.
Widget Seviyesinde Tema Geçersiz Kılma (Override)
Theme(
data: Theme.of(context).copyWith(
colorScheme: Theme.of(context).colorScheme.copyWith(primary: Colors.red),
),
child: ElevatedButton(
onPressed: () {},
child: Text('Özel Renkli Buton'),
),
)Bölüm 3 Konu 12'de öğrendiğimiz copyWith() kalıbı burada tekrar karşımıza çıkıyor — var olan temayı temel alıp, sadece belirli bir kısmını değiştirerek, sadece bir widget alt ağacı için geçerli olan yerel bir tema oluşturabilirsin.
🎯 Bu Dersten Çıkarılması Gerekenler
ThemeData, uygulamanın genelinde tutarlı stil (renk, font, buton görünümü) tanımlamanı sağlayan merkezi bir yapılandırma nesnesidir.Theme.of(context), widget ağacında "en yakın" tanımlı temayı bulur — bu,InheritedWidgetmekanizmasına dayanır (Bölüm 8'de tam işleyeceğiz).ColorScheme.fromSeed(), tek bir ana renkten, Material Design kurallarına uygun bütünsel bir renk paleti üretir;primary/onPrimarygibi çiftler, renk ve o rengin üzerine yazı rengini eşleştirir.darkTheme+themeMode, karanlık mod desteğini sağlar;ThemeMode.system, cihaz ayarına göre otomatik seçim yapar.Themewidget'ı ile, bir widget alt ağacı için yerel olarak temayı geçersiz kılabilirsin.
📝 Ödevler
- [ ]
ThemeDataile uygulamana özel bir ana renk, buton stili ve metin teması tanımla, tüm uygulamada tutarlı şekilde kullan. - [ ]
ColorScheme.fromSeed()ile tek bir renkten tam bir renk paleti oluştur,primary/onPrimaryile bir widget stilini uygula. - [ ] Karanlık mod / aydınlık mod arasında geçiş yapabilen bir switch ekle (
themeModeile). - [ ]
Themewidget'ı vecopyWith()kullanarak, sadece belirli bir widget için yerel bir tema geçersiz kılması yap. - [ ] Kendi cümlelerinle, "Theme.of(context) nasıl doğru temayı buluyor" sorusunu, widget ağacı ve context kavramlarıyla ilişkilendirerek açıkla (tahmin edebildiğin kadarıyla — Bölüm 8'de tam mekanizmayı göreceğiz).
Sıradaki konu: Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)