Flutter'da Switch Kullanımı ve Switch ile Dinamik Tema (Dark Mode) Yönetimi
Mobil uygulama geliştirirken kullanıcıya "Evet/Hayır", "Açık/Kapalı" gibi iki seçenekli bir tercih sunmamız gerektiğinde akla gelen ilk bileşen Switch (Anahtar) widget'ıdır. Özellikle ayarlar menülerinde, bildirim tercihlerinde veya temayı değiştirmek (Dark Mode/Light Mode) gibi senaryolarda sıkça kullanılır.
Flutter Switch Kullanımı – (Material 3 Uyumlu)
Flutter’da Switch, kullanıcıdan açık / kapalı (true / false) şeklinde ikili seçim almak için kullanılan bir bileşendir. Genellikle:
Dark Mode
Bildirim Aç/Kapat
Wi-Fi / Bluetooth
Gizlilik ayarları
Uygulama içi tercih ayarları
gibi durumlarda kullanılır.
Bu makalede:
Switch temel kullanımı
Stateful yönetimi
SwitchListTile kullanımı
Material 3 tasarım uyumu
Tema özelleştirme
Gerçek bir Ayarlar ekranı örneği
adım adım anlatılacaktır.
1️⃣ Switch Nedir?
Switch, Flutter’da bool tipinde bir değerle çalışan toggle (anahtar) bileşenidir.
Temel mantık:
bool isEnabled = false;
Switch değeri değiştiğinde:
onChanged: (value) {
setState(() {
isEnabled = value;
});
}
2️⃣ Temel Switch Kullanımı
Basit Örnek
import 'package:flutter/material.dart';
class SwitchExample extends StatefulWidget {
const SwitchExample({super.key});
@override
State<SwitchExample> createState() => _SwitchExampleState();
}
class _SwitchExampleState extends State<SwitchExample> {
bool isDarkMode = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Switch Örneği")),
body: Center(
child: Switch(
value: isDarkMode,
onChanged: (value) {
setState(() {
isDarkMode = value;
});
},
),
),
);
}
}
Mantık Akışı
Switch → onChanged tetiklenir → setState → UI yeniden çizilir
3️⃣ Switch Özellikleri
| Özellik | Açıklama |
|---|---|
| value | Switch’in mevcut durumu (true/false) |
| onChanged | Değer değiştiğinde çalışır |
| activeColor | Açık durum rengi |
| inactiveThumbColor | Kapalı top rengi |
| inactiveTrackColor | Kapalı arka plan rengi |
4️⃣ SwitchListTile Kullanımı
Eğer Switch yanında metin göstermek istiyorsanız en pratik yol:
SwitchListTile(
title: const Text("Dark Mode"),
subtitle: const Text("Karanlık temayı etkinleştir"),
value: isDarkMode,
onChanged: (value) {
setState(() {
isDarkMode = value;
});
},
)
Avantajları:
Otomatik hizalama
Daha düzenli görünüm
Ayarlar ekranları için ideal
5️⃣ Material 3 Uyumlu Switch Tasarımı
Material 3 için useMaterial3: true aktif olmalıdır:
MaterialApp(
theme: ThemeData(
useMaterial3: true,
),
home: const SwitchExample(),
);
Material 3 Switch Özelleştirme
Switch(
value: isDarkMode,
onChanged: (value) {
setState(() {
isDarkMode = value;
});
},
activeTrackColor: Colors.deepPurple,
activeColor: Colors.white,
)
6️⃣ Gerçek Bir Ayarlar Ekranı Örneği
Aşağıdaki örnek modern bir Ayarlar ekranıdır.
import 'package:flutter/material.dart';
class SettingsPage extends StatefulWidget {
const SettingsPage({super.key});
@override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
bool darkMode = false;
bool notifications = true;
bool location = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Ayarlar"),
),
body: ListView(
children: [
SwitchListTile(
title: const Text("Dark Mode"),
subtitle: const Text("Karanlık temayı kullan"),
value: darkMode,
onChanged: (value) {
setState(() {
darkMode = value;
});
},
),
SwitchListTile(
title: const Text("Bildirimler"),
subtitle: const Text("Anlık bildirimleri aç/kapat"),
value: notifications,
onChanged: (value) {
setState(() {
notifications = value;
});
},
),
SwitchListTile(
title: const Text("Konum Servisi"),
subtitle: const Text("Konum erişimine izin ver"),
value: location,
onChanged: (value) {
setState(() {
location = value;
});
},
),
],
),
);
}
}
7️⃣ Clean Code Versiyonu (Widget’lara Bölünmüş)
Daha profesyonel yaklaşım:
class SettingsSwitch extends StatelessWidget {
final String title;
final String subtitle;
final bool value;
final Function(bool) onChanged;
const SettingsSwitch({
super.key,
required this.title,
required this.subtitle,
required this.value,
required this.onChanged,
});
@override
Widget build(BuildContext context) {
return SwitchListTile(
title: Text(title),
subtitle: Text(subtitle),
value: value,
onChanged: onChanged,
);
}
}
Kullanımı:
SettingsSwitch(
title: "Dark Mode",
subtitle: "Karanlık temayı kullan",
value: darkMode,
onChanged: (value) {
setState(() {
darkMode = value;
});
},
),
8️⃣ Switch ile Dark Mode Gerçekten Değiştirme
Switch sadece UI değiştirir. Gerçek tema değiştirmek için:
themeMode: darkMode ? ThemeMode.dark : ThemeMode.light,
Bunu genellikle Provider, Riverpod veya Bloc ile yönetmek profesyonel yaklaşımdır.
9️⃣ Switch Kullanırken Yapılan Hatalar
❌ bool yerine String kullanmak
❌ setState çağırmayı unutmak
❌ value null bırakmak
❌ Çok fazla Switch’i tek ekrana yığmak
🔟 Switch Ne Zaman Kullanılmalı?
| Senaryo | Switch Uygun mu? |
|---|---|
| Aç/Kapat | ✅ |
| Çoklu seçim | ❌ (Checkbox) |
| Tek seçim | ❌ (Radio) |
| Anında ayar değişimi | ✅ |
🎯 Sonuç
Flutter Switch:
Basit
Performanslı
Material 3 uyumlu
Ayarlar ekranları için ideal
State yönetimi öğrenmek için harika bir başlangıç bileşeni
🚀 Makale İçin Başlık Önerileri
Flutter Switch Widget Detaylı Rehberi (Material 3 Uyumlu)
Flutter’da Switch Kullanımı ve Ayarlar Ekranı Tasarımı
Flutter Toggle Switch ile Modern UI Geliştirme
Flutter SwitchListTile ile Profesyonel Ayar Ekranı
🔎 SEO Etiketleri
flutter switch, flutter switchlisttile, flutter material 3, flutter ayarlar ekranı, flutter toggle button, flutter dark mode switch, flutter state management, flutter ui component, flutter bool widget, flutter form elemanları
1. Switch Widget Nedir ve Nasıl Çalışır?
Switch, temel olarak iki parçadan oluşur:
Thumb (Başparmak/Düğme): Hareket eden yuvarlak kısımdır.
Track (Ray/Yol): Düğmenin üzerinde kaydığı arka plan şerididir.
Flutter'da Switch widget'ı, kendi durumunu (state) tutmaz. Yani üzerine tıklandığında görüntüsünün değişmesi için ona dışarıdan bir bool değer vermeniz ve bu değer değiştiğinde ekranı setState ile yenilemeniz gerekir.
Temel Parametreler
value:
true(açık) veyafalse(kapalı) değerini alır. Switch'in o anki konumunu belirler.onChanged: Kullanıcı Switch'i sürüklediğinde veya tıkladığında tetiklenen fonksiyondur. Yeni değeri (
bool) parametre olarak döner.
2. Basit Switch Kullanımı
Bir Switch'i ekranda görebilmek ve yönetebilmek için mutlaka bir StatefulWidget içerisinde tanımlamalıyız.
bool _bildirimlerAcikMi = false;
Switch(
value: _bildirimlerAcikMi,
onChanged: (bool yeniDeger) {
setState(() {
_bildirimlerAcikMi = yeniDeger;
});
// Burada örneğin veritabanına kayıt işlemi yapılabilir
print("Bildirim durumu: $_bildirimlerAcikMi");
},
)
Bu kod bloğunda, kullanıcı anahtara bastığında onChanged tetiklenir, _bildirimlerAcikMi değişkeni güncellenir ve setState sayesinde Switch'in görseli yeni konuma (açık veya kapalı) geçer.
3. Kullanıcı Deneyimi İçin: SwitchListTile
Genellikle Switch'ler tek başına kullanılmaz; yanında ne işe yaradığını anlatan bir metin bulunur. Row ve Text kullanarak bunu elle yapmak yerine, Flutter'ın sunduğu SwitchListTile widget'ını kullanmak en doğru yaklaşımdır.
Avantajları:
Sadece anahtara değil, metnin olduğu tüm satıra tıklandığında Switch tetiklenir.
Başlık (title), alt başlık (subtitle) ve simge (secondary) desteği sunar.
SwitchListTile(
title: const Text('Karanlık Mod'),
subtitle: const Text('Uygulama temasını koyu yapar'),
secondary: const Icon(Icons.dark_mode), // Sol tarafa ikon ekler
value: _karanlikMod,
onChanged: (bool value) {
setState(() {
_karanlikMod = value;
});
},
)
4. Renk ve Tasarım Özelleştirme
Uygulamanızın renk paletine uyması için Switch'in renklerini activeColor, activeTrackColor gibi parametrelerle değiştirebilirsiniz.
activeColor: Açık konumdayken Düğme (Thumb) rengi.
activeTrackColor: Açık konumdayken Ray (Track) rengi.
inactiveThumbColor: Kapalı konumdayken Düğme rengi.
inactiveTrackColor: Kapalı konumdayken Ray rengi.
Daha gelişmiş bir özelleştirme için (örneğin butonun üzerine ikon koymak) thumbIcon özelliğini kullanabilirsiniz (Material 3 ile daha yaygınlaşmıştır):
Switch(
value: _wifiAcik,
onChanged: (val) => setState(() => _wifiAcik = val),
thumbIcon: MaterialStateProperty.resolveWith<Icon?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return const Icon(Icons.check); // Açıkken onay işareti
}
return const Icon(Icons.close); // Kapalıyken çarpı işareti
},
),
)
5. Platform Duyarlılığı: Switch.adaptive
iOS ve Android kullanıcıları farklı tasarım dillerine alışıktır. Android'de Material Design Switch beklenirken, iOS'ta (iPhone) Cupertino tarzı yeşil-beyaz bir anahtar beklenir.
Tek bir kod yazıp her iki platformda da "doğal" görünüm elde etmek için Switch.adaptive yapıcısını (constructor) kullanırız.
Switch.adaptive(
value: _konumServisi,
onChanged: (val) {
setState(() => _konumServisi = val);
},
activeColor: Colors.green, // iOS'ta vurgu rengi olur
)
6. Tam Örnek Kod
Aşağıdaki kodu kopyalayıp yeni bir Flutter projesindeki main.dart dosyasına yapıştırarak tüm özellikleri deneyebilirsiniz.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true), // Material 3 Aktif
home: const SwitchOrnekSayfasi(),
);
}
}
class SwitchOrnekSayfasi extends StatefulWidget {
const SwitchOrnekSayfasi({super.key});
@override
State<SwitchOrnekSayfasi> createState() => _SwitchOrnekSayfasiState();
}
class _SwitchOrnekSayfasiState extends State<SwitchOrnekSayfasi> {
bool isSwitched = false;
bool isTileSwitched = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter Switch Rehberi')),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
// 1. Basit Switch
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Basit Switch:", style: TextStyle(fontSize: 18)),
Switch(
value: isSwitched,
onChanged: (value) {
setState(() {
isSwitched = value;
});
},
activeColor: Colors.orange,
),
],
),
const Divider(),
// 2. SwitchListTile (Önerilen)
SwitchListTile(
title: const Text("Bildirimleri Aç"),
subtitle: const Text("Uygulama içi bildirimler"),
secondary: const Icon(Icons.notifications),
value: isTileSwitched,
onChanged: (value) {
setState(() {
isTileSwitched = value;
});
},
),
const Divider(),
// 3. Adaptive Switch (iOS/Android uyumlu)
const Text("Adaptive Switch (Platforma Göre):"),
Switch.adaptive(
value: isSwitched,
onChanged: (val) => setState(() => isSwitched = val),
),
],
),
),
);
}
}
Sonuç
Switch widget'ı, basit görünmesine rağmen kullanıcı etkileşimi açısından kritik bir bileşendir. Özellikle listelerde kullanırken SwitchListTile tercih etmeniz, kullanıcı deneyimini (UX) önemli ölçüde artıracaktır. Material 3 desteği ile gelen ikonlu ve renkli tasarımları kullanarak uygulamanızı daha modern hale getirebilirsiniz.
Harika! Switch kullanımını öğrendikten sonra bunu en yaygın senaryo olan Tema Değiştirme (Dark/Light Mode) ile pekiştirmek, bloğunuz (https://www.google.com/search?q=pardusflutter.blogspot.com) için de çok değerli bir içerik olacaktır.
İşte Flutter'da Switch kullanarak dinamik tema değiştirmeyi anlatan, "Kopyala-Yapıştır" yapıp deneyebileceğiniz kapsamlı bir makale taslağı:
Flutter ile Dinamik Tema Yönetimi: Switch Kullanarak Dark/Light Mode Geçişi
Modern mobil uygulamaların olmazsa olmazı "Karanlık Mod" (Dark Mode) özelliğidir. Kullanıcılar, göz yorgunluğunu azaltmak veya pil tasarrufu sağlamak için bu modu sıkça tercih ederler.
Bu yazıda, bir önceki dersimizde öğrendiğimiz Switch widget'ını kullanarak, uygulamanın temasını çalışma anında (runtime) nasıl değiştirebileceğimizi ve bu yapıyı en basit haliyle nasıl kuracağımızı inceleyeceğiz.
Temel Mantık: MaterialApp ve ThemeMode
Flutter'da tema değiştirmek sanıldığı kadar zor değildir. MaterialApp widget'ı bize doğuştan üç önemli parametre sunar:
theme: Uygulamanın varsayılan (genellikle aydınlık) teması.
darkTheme: Uygulamanın karanlık mod teması.
themeMode: Hangi temanın aktif olacağını belirleyen ayar (
ThemeMode.light,ThemeMode.darkveyaThemeMode.system).
Bizim yapacağımız işlem şudur: Switch anahtarını themeMode parametresine bağlamak ve anahtar değiştikçe MaterialApp'i yeniden çizdirmek.
Adım Adım Uygulama
Bu örnekte, ekstra bir paket (Provider, Bloc vb.) kullanmadan, Flutter'ın kendi yetenekleri (ValueNotifier) ile en sade ve anlaşılır yöntemi kullanacağız.
1. Tema Verisini Yönetmek
Uygulamanın her yerinden erişilebilecek bir "Tema Bildiricisi"ne ihtiyacımız var. Bunun için ValueNotifier kullanacağız. Bu yapı, içindeki değer değiştiğinde MaterialApp'e haber verecek.
2. Arayüzü Oluşturmak
Switch'i koyacağımız bir ayarlar sayfası tasarlayacağız. Switch açıldığında ThemeMode.dark, kapandığında ThemeMode.light değerini tetikleyeceğiz.
3. Tam Kod Örneği
Aşağıdaki kodu projenizin main.dart dosyasına yapıştırarak hemen test edebilirsiniz.
import 'package:flutter/material.dart';
void main() {
runApp(const BenimUygulamam());
}
// 1. TEMA YÖNETİCİSİ:
// Uygulamanın karanlık modda olup olmadığını takip eden basit bir dinleyici.
// Varsayılan olarak 'false' (Aydınlık Mod) ile başlar.
final ValueNotifier<bool> temaYonetici = ValueNotifier(false);
class BenimUygulamam extends StatelessWidget {
const BenimUygulamam({super.key});
@override
Widget build(BuildContext context) {
// ValueListenableBuilder: temaYonetici her değiştiğinde burayı yeniden çizer.
return ValueListenableBuilder<bool>(
valueListenable: temaYonetici,
builder: (context, isDark, child) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Tema Değiştirme Örneği',
// AYDINLIK TEMA AYARLARI
theme: ThemeData(
useMaterial3: true,
brightness: Brightness.light,
colorSchemeSeed: Colors.blue, // Ana renk mavi
scaffoldBackgroundColor: Colors.white,
appBarTheme: const AppBarTheme(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
),
// KARANLIK TEMA AYARLARI
darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorSchemeSeed: Colors.blue, // Karanlıkta da mavi tonları korunsun
scaffoldBackgroundColor: Colors.grey[900], // Koyu gri arka plan
),
// TEMA MODU SEÇİMİ (Switch'ten gelen değere göre)
themeMode: isDark ? ThemeMode.dark : ThemeMode.light,
home: const AyarlarSayfasi(),
);
},
);
}
}
class AyarlarSayfasi extends StatelessWidget {
const AyarlarSayfasi({super.key});
@override
Widget build(BuildContext context) {
// Mevcut temanın koyu mu açık mı olduğunu anlamak için
bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold(
appBar: AppBar(
title: const Text("Ayarlar"),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
const Text(
"Görünüm Ayarları",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
Card(
elevation: 2,
child: Column(
children: [
// SwitchListTile Kullanımı
SwitchListTile(
title: const Text("Karanlık Mod"),
subtitle: Text(isDarkMode ? "Açık" : "Kapalı"),
secondary: Icon(
isDarkMode ? Icons.dark_mode : Icons.light_mode,
color: isDarkMode ? Colors.yellow : Colors.orange,
),
value: temaYonetici.value, // Global yöneticiden değeri al
onChanged: (val) {
// Değeri değiştir, ValueNotifier tüm uygulamayı günceller
temaYonetici.value = val;
},
),
],
),
),
const SizedBox(height: 20),
// Görsel Test İçin Bir Buton
Center(
child: ElevatedButton.icon(
onPressed: () {},
icon: const Icon(Icons.save),
label: const Text("Örnek Buton"),
),
),
],
),
);
}
}
Kodun Analizi
ValueNotifier:
temaYoneticiadında global bir değişken oluşturduk. Bu değişken sadecetrueveyafalsetutar ama değiştiğinde kendisine bağlı widget'ları uyarır.ValueListenableBuilder:
MaterialAppwidget'ını bununla sarmaladık. BöylecetemaYoneticiher değiştiğindeMaterialAppyeniden derlenir ve yeni temayı (ThemeMode) uygular.SwitchListTile: Kullanıcı anahtarı değiştirdiğinde
temaYonetici.value = val;kodu çalışır. Bu tetikleme, en tepedekiBuilder'ı çalıştırır ve ekran anında kararır veya aydınlanır.
İpucu: Kalıcı Ayarlar
Bu örnekte uygulama kapatılıp açıldığında ayarlar sıfırlanır. Gerçek bir uygulamada, kullanıcının tercihini hafızada tutmak için shared_preferences paketi kullanılır. Kullanıcı Switch'e bastığında değeri hem temaYonetici'ye hem de telefonun hafızasına kaydetmek gerekir.
Material 3 uyumlu, animasyonlu Dark/Light Mode geçişli bir Flutter örneği
Bu örnekte:
🌙 Switch ile tema değişecek
🎬 Yumuşak animasyon olacak
🎨 Material 3 tasarım kullanılacak
🧠 Global state mantığı gösterilecek
✨ AnimatedSwitcher + AnimatedContainer kullanılacak
🌙 Animasyonlu Dark / Light Mode Örneği
✅ Özellikler
Switch ile anında tema değişimi
400ms animasyon süresi
Arka plan rengi animasyonlu geçiş
Icon animasyonu (☀️ / 🌙)
🔥 TAM ÇALIŞAN KOD
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isDarkMode = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.deepPurple,
brightness: Brightness.light,
),
darkTheme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.deepPurple,
brightness: Brightness.dark,
),
home: HomePage(
isDarkMode: isDarkMode,
onChanged: (value) {
setState(() {
isDarkMode = value;
});
},
),
);
}
}
class HomePage extends StatelessWidget {
final bool isDarkMode;
final Function(bool) onChanged;
const HomePage({
super.key,
required this.isDarkMode,
required this.onChanged,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Animasyonlu Tema"),
centerTitle: true,
),
body: AnimatedContainer(
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
color: Theme.of(context).colorScheme.background,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 400),
transitionBuilder: (child, animation) {
return RotationTransition(
turns: animation,
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
child: Icon(
isDarkMode ? Icons.dark_mode : Icons.light_mode,
key: ValueKey<bool>(isDarkMode),
size: 100,
),
),
const SizedBox(height: 40),
Switch(
value: isDarkMode,
onChanged: onChanged,
),
],
),
),
),
);
}
}
🎬 Kullanılan Animasyonlar
1️⃣ AnimatedContainer
Arka plan geçişini yumuşatır.
2️⃣ AnimatedSwitcher
Icon değişimini animasyonlu yapar.
3️⃣ Rotation + Fade
Icon hem döner hem solup belirir.
🎨 Daha Profesyonel Yapmak İçin
Eğer projeni büyütmek istiyorsan:
✅
Providerile global tema yönetimi✅
Riverpodile reactive yapı✅
SharedPreferencesile temayı kalıcı kaydetme✅ Hero animasyonlu geçiş
✅ Custom Switch tasarımı
Yorumlar
Yorum Gönder