Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
Dizi · 11/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 10 başlık
- Neden Kaydırılabilir (Scrollable) Widget'lara İhtiyaç Var?
- SingleChildScrollView — Basit Kaydırma
- ListView — Kaydırılabilir Liste
- ListView.builder — Büyük Listeler İçin Kritik Bir Kalıp
- ListView.separated — Öğeler Arasına Ayırıcı Ekleme
- GridView — Izgara Düzeni
- "Builder Pattern" — Neden Bu Kadar Yaygın?
- Gerçek Bir Örnek — Model Listesi ile
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
Neden Kaydırılabilir (Scrollable) Widget'lara İhtiyaç Var?
Bölüm 2'de öğrendiğimiz Column, çocuklarını dikey sıralar — ama eğer içerik ekran boyutunu aşarsa, Column kaydırma (scroll) yapmaz, sadece taşar ve bir hata/uyarı gösterir (sarı-siyah çizgili bir "overflow" göstergesi). Kaydırılabilir widget'lar, bu sorunu çözer.
SingleChildScrollView — Basit Kaydırma
SingleChildScrollView(
child: Column(
children: [
Container(height: 200, color: Colors.red),
Container(height: 200, color: Colors.blue),
Container(height: 200, color: Colors.green),
],
),
)SingleChildScrollView, tek bir çocuğu (genelde bir Column) alır ve içerik ekrandan taşarsa, kullanıcının kaydırabilmesini sağlar. Bölüm 2 Konu 5'te öğrendiğimiz child parametresini hatırlarsan — burada da tek bir çocuk alıyor, tıpkı Center/Padding gibi.
Ne zaman kullanılır? İçeriğin sabit ve az sayıda olduğu, ama ekrana her zaman sığmayabileceği durumlarda (örneğin bir form ekranı).
ListView — Kaydırılabilir Liste
ListView(
children: [
ListTile(title: Text('Öğe 1')),
ListTile(title: Text('Öğe 2')),
ListTile(title: Text('Öğe 3')),
],
)ListView, Column + SingleChildScrollView'in birleşimi gibi düşünülebilir — hem dikey sıralar hem otomatik olarak kaydırılabilir yapar. ListTile, liste öğeleri için hazır, standart bir düzen sunan bir widget'tır (başlık, alt başlık, ikon gibi yuvaları vardır).
ListView.builder — Büyük Listeler İçin Kritik Bir Kalıp
ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Öğe ${index + 1}'),
);
},
)Yukarıdaki basit ListView, tüm çocukları (children: [...]) anında oluşturur — 100 öğeli bir liste için, 100 widget'ı hemen, ekranda görünmese bile oluşturmuş olursun. Bu, Dart Bölüm 13 Konu 62'de öğrendiğimiz bellek verimliliği açısından israftır.
ListView.builder, bunun yerine "lazy" (tembel) çalışır — Dart Bölüm 11 Konu 51'de öğrendiğimiz lazy evaluation kavramını hatırlarsan, burada aynı felsefe uygulanıyor: itemBuilder fonksiyonu, sadece ekranda görünmesi gereken öğeler için çağrılır. Kullanıcı aşağı kaydırdıkça, yeni öğeler için itemBuilder o an çağrılır; ekrandan çıkan öğeler ise bellekten temizlenir (Dart Bölüm 13'te öğrendiğimiz garbage collection'a aday olur).
itemBuilder parametresi — Dart bilginle çözümleme:
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Öğe ${index + 1}'));
}Bu, Dart Bölüm 5'te öğrendiğimiz anonim fonksiyondur — iki parametre alıyor (context ve index), bir Widget döndürüyor. index, Dart Bölüm 4'te öğrendiğimiz liste indekslerine benzer bir mantıkla, kaçıncı öğenin oluşturulduğunu belirtir (0'dan başlar).
ListView.separated — Öğeler Arasına Ayırıcı Ekleme
ListView.separated(
itemCount: 20,
itemBuilder: (context, index) => ListTile(title: Text('Öğe $index')),
separatorBuilder: (context, index) => Divider(),
)separatorBuilder, her öğe arasına (öncesine değil, sonrasına da değil, tam arasına) bir widget (genelde Divider — ince bir çizgi) ekler. Bu, itemBuilder'ın aynı lazy mantığıyla çalışır.
GridView — Izgara Düzeni
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // 2 sütun
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemCount: 10,
itemBuilder: (context, index) {
return Container(
color: Colors.blue[100 * ((index % 8) + 1)],
child: Center(child: Text('Öğe $index')),
);
},
)GridView, ListView'e çok benzer bir mantıkla çalışır (aynı builder kalıbı) ama öğeleri ızgara (grid) düzeninde, birden fazla sütunda gösterir. SliverGridDelegateWithFixedCrossAxisCount, "sabit sayıda sütun" kullanmanı sağlar (crossAxisCount: 2 — 2 sütunlu bir ızgara).
"Builder Pattern" — Neden Bu Kadar Yaygın?
ListView.builder, GridView.builder, ve ilerleyen derslerde göreceğin birçok widget, aynı deseni (pattern) paylaşır: "kaç öğe olduğunu söyle, her öğenin nasıl görüneceğini tarif eden bir fonksiyon ver, ben gerektiğinde çağırırım." Bu, Dart Bölüm 5'te öğrendiğimiz higher-order function kavramının (fonksiyonu parametre olarak alan fonksiyon) Flutter'daki en yaygın uygulamasıdır.
Neden List<Widget> yerine bu desen tercih ediliyor?
// KÖTÜ pratik (büyük listeler için) — hepsini önceden oluşturur
ListView(children: List.generate(1000, (i) => ListTile(title: Text('$i'))))
// İYİ pratik — sadece görünenler oluşturulur
ListView.builder(itemCount: 1000, itemBuilder: (context, i) => ListTile(title: Text('$i')))Dart Bölüm 4 Konu 20'de List.generate'i öğrenmiştik — burada onu kullanmak teknik olarak çalışır, ama 1000 widget'ı anında oluşturur. ListView.builder, aynı sonucu çok daha verimli şekilde, lazy olarak sağlar. Bu, Bölüm 9'da (performans) tam olarak işleyeceğimiz bir konunun erken bir önizlemesi.
Gerçek Bir Örnek — Model Listesi ile
class Urun {
final String ad;
final double fiyat;
Urun(this.ad, this.fiyat);
}
class UrunListesi extends StatelessWidget {
final List<Urun> urunler;
const UrunListesi({super.key, required this.urunler});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: urunler.length, // Dart Bölüm 4'te öğrendiğimiz .length
itemBuilder: (context, index) {
final urun = urunler[index]; // Dart'ta öğrendiğimiz indeksli erişim
return ListTile(
title: Text(urun.ad),
trailing: Text('${urun.fiyat} TL'),
);
},
);
}
}Bu, Dart Bölüm 6'da öğrendiğimiz class'lar ile Flutter'ın builder deseninin birleşimini gösteriyor — gerçek bir uygulamada, sabit sayıda öğe yerine, veri modelinden gelen (bir API'den, bir veritabanından) listeleri bu şekilde göstereceksin.
🎯 Bu Dersten Çıkarılması Gerekenler
SingleChildScrollView, tek bir çocuğu (genelde Column) kaydırılabilir yapar; küçük, sabit içerikler için uygundur.ListView, dikey kaydırılabilir bir liste oluşturur;ListView.builder, büyük listelerde lazy (sadece görünenleri oluşturarak) çalışır — Dart'taki lazy evaluation'a benzer bir performans optimizasyonu.itemBuilder, bir anonim fonksiyondur (context, index alır, widget döndürür) — "builder pattern"in temelidir.GridView.builder, aynı deseni ızgara düzeninde uygular.ListView.separated, öğeler arasına ayırıcı widget'lar eklemeyi sağlar.
📝 Ödevler
- [ ]
SingleChildScrollViewiçinde, ekranı aşan yükseklikte birkaçContaineroluştur, kaydırmayı test et. - [ ]
ListView.builderile 50 elemanlı bir liste oluştur, her satırıListTileile göster. - [ ]
ListView.separatedkullanarak, öğeler arasınaDividerekle. - [ ]
GridView.builderile 2 sütunlu, en az 10 öğeli bir ızgara oluştur. - [ ] Kendi tanımladığın bir class'tan (örn.
Urun) oluşan bir listeyi,ListView.builderile gösteren bir widget yaz (Konu 11'dekiUrunListesiörneğine benzer).
Sıradaki konu: Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi