Flutter ListView Kullanımı: Statik ve Dinamik Listeler Oluşturma

Mobil uygulamaların neredeyse tamamında verileri alt alta veya yan yana sıralamak için listeler kullanılır. Flutter'da listeler oluşturmak hem çok esnek hem de performanslıdır.


Flutter'da ekrana sığmayan, kaydırılabilir (scrollable) içerikler oluşturmak istediğimizde kullandığımız en temel araç ListView widget'ıdır. Sadece birkaç elemanı olan statik listelerden, binlerce elemanı olan dinamik veri setlerine kadar her şeyi ListView ile yönetebiliriz.

Flutter'da liste oluşturmanın 3 temel yöntemini ve liste elemanlarını görselleştirmek için kullandığımız ListTile yapısını inceleyeceğiz.


1. Temel Kullanım: Standart ListView

Eğer listenizdeki eleman sayısı azsa (örneğin bir ayarlar menüsü veya 10-15 elemanlı sabit bir liste) standart ListView kullanabilirsiniz. Standart ListView, içindeki tüm elemanları aynı anda belleğe yükler ve çizer.

Kullanım Örneği:

Dart:
ListView(
  padding: const EdgeInsets.all(8),
  children: <Widget>[
    Container(
      height: 50,
      color: Colors.amber[600],
      child: const Center(child: Text('A Elemanı')),
    ),
    Container(
      height: 50,
      color: Colors.amber[500],
      child: const Center(child: Text('B Elemanı')),
    ),
    Container(
      height: 50,
      color: Colors.amber[100],
      child: const Center(child: Text('C Elemanı')),
    ),
  ],
)

⚠️ Önemli Not: Eğer binlerce verilik bir liste yapacaksanız, bu yöntemi kullanmamalısınız. Tüm verileri aynı anda yüklemeye çalışmak uygulamanızı dondurabilir veya bellek yetersizliğinden çökmesine sebep olabilir.


2. Performansın Zirvesi: ListView.builder

Eğer internetten çektiğiniz uzun bir veriyi (örneğin Twitter akışı, e-posta kutusu) gösterecekseniz ihtiyacınız olan şey ListView.builder'dır.

Bu yapı "tembel yükleme" (lazy loading) mantığıyla çalışır. Sadece ekranda görünen ve görünmek üzere olan elemanları oluşturur. Siz aşağı kaydırdıkça, yukarıda kalan elemanlar bellekten silinir ve yenileri oluşturulur. Bu sayede 10.000 elemanlı bir liste bile sıfır kasma ile çalışır.

Kullanım Örneği:

Dart:
final List<String> isimler = ['Ali', 'Ayşe', 'Mehmet', 'Fatma', 'Can'];

ListView.builder(
  itemCount: isimler.length, // Listenin kaç elemanlı olacağı
  itemBuilder: (BuildContext context, int index) {
    // index, o an çizilmekte olan elemanın sırasını verir (0, 1, 2...)
    return Container(
      height: 50,
      margin: const EdgeInsets.all(2),
      color: Colors.blue[100],
      child: Center(
        child: Text('${isimler[index]} (Index: $index)'),
      ),
    );
  },
)

3. Araya Ayırıcı Koymak: ListView.separated

Eğer liste elemanlarınızın arasına ince bir çizgi (Divider), bir boşluk veya reklam gibi farklı bir widget koymak isterseniz ListView.separated kurtarıcınızdır. ListView.builder'ın sunduğu tüm performans avantajlarına sahiptir.

Ekstra olarak separatorBuilder adında bir parametre alır ve her elemanın arasına burada belirttiğiniz widget'ı koyar.

Kullanım Örneği:

Dart:
ListView.separated(
  itemCount: 25,
  itemBuilder: (BuildContext context, int index) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text('Öğe $index'),
    );
  },
  separatorBuilder: (BuildContext context, int index) {
    // Her elemanın arasına ince gri bir çizgi çizer
    return const Divider(color: Colors.grey); 
  },
)

4. Liste Elemanlarını Tasarlamak: ListTile

Liste elemanlarını oluştururken her seferinde Row'lar ve Column'lar ile sıfırdan tasarım yapmak yorucu olabilir. Flutter, özellikle listeler için tasarlanmış, Material Design standartlarına uygun ListTile widget'ını sunar.

ListTile, bir liste elemanını mantıksal bölgelere ayırır:

  • leading: En soldaki ikon veya profil fotoğrafı.

  • title: Ana başlık.

  • subtitle: Başlığın altındaki alt metin.

  • trailing: En sağdaki ikon (örneğin bir ok işareti veya favori butonu).

Kullanım Örneği:

Dart:
ListView.builder(
  itemCount: 10,
  itemBuilder: (context, index) {
    return Card( // Liste elemanlarına hafif bir gölge ve kart görünümü verir
      child: ListTile(
        leading: CircleAvatar(
          child: Text('${index + 1}'),
        ),
        title: Text('Kullanıcı Adı $index'),
        subtitle: const Text('Bu kullanıcının kısa açıklaması burada yer alır.'),
        trailing: const Icon(Icons.arrow_forward_ios),
        onTap: () {
          // Elemana tıklandığında yapılacak işlemler
          print('Tıklandı: $index');
        },
      ),
    );
  },
)

Özetle Ne Öğrendik?

  • Sabit ve az elemanlı listeler için ListView kullanıyoruz.

  • Uzun, dinamik ve performans gerektiren listeler için ListView.builder kullanıyoruz.

  • Elemanlar arasına ayırıcı çizgiler eklemek için ListView.separated tercih ediyoruz.

  • Liste elemanlarını şık ve hızlı bir şekilde tasarlamak için ListTile widget'ından faydalanıyoruz.


📘 Flutter’da Listeler (List & ListView)

1️⃣ Liste (List) Nedir?

Liste, birden fazla veriyi tek bir değişken içinde saklamamızı sağlar.

🎯 Örnek:

List<String> meyveler = ["Elma", "Armut", "Muz"];

Bu liste 3 eleman içerir.


2️⃣ Liste Türleri

🔹 String Listesi

List<String> isimler = ["Ahmet", "Mehmet", "Ayşe"];

🔹 Integer Listesi

List<int> sayilar = [10, 20, 30];

🔹 Dinamik Liste

List karisik = ["Ali", 15, true];

⚠️ Gerçek projelerde tip belirtmek daha güvenlidir.


3️⃣ Liste Metotları (Çok Önemli)

➕ Eleman Ekleme

isimler.add("Fatma");

➖ Eleman Silme

isimler.remove("Ahmet");

🔢 Index ile erişim

print(isimler[0]); // İlk eleman

📏 Uzunluk

print(isimler.length);

🖥️ 4️⃣ Flutter’da Listeyi Ekranda Gösterme

Normal Dart listesi oluşturduk ama bunu ekranda göstermek için:

👉 ListView kullanılır.


🧱 5️⃣ ListView Nedir?

Ekranda kaydırılabilir liste oluşturmamızı sağlar.


🔹 Basit ListView Örneği

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: ListeOrnek(),
    debugShowCheckedModeBanner: false,
  ));
}

class ListeOrnek extends StatelessWidget {
  final List<String> meyveler = ["Elma", "Armut", "Muz", "Çilek"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Meyve Listesi")),
      body: ListView(
        children: meyveler.map((meyve) {
          return ListTile(
            title: Text(meyve),
          );
        }).toList(),
      ),
    );
  }
}

🚀 6️⃣ ListView.builder (Performans İçin Önemli)

Gerçek projelerde büyük listeler olur (1000+ veri).

Bu yüzden:

👉 ListView.builder kullanılır.


🔹 Builder Örneği

body: ListView.builder(
  itemCount: meyveler.length,
  itemBuilder: (context, index) {
    return ListTile(
      leading: Icon(Icons.apple),
      title: Text(meyveler[index]),
    );
  },
),

🔎 Açıklama:

ParametreNe işe yarar
itemCount            Kaç eleman var
itemBuilder            Her satırı üretir
index            O anki elemanın sıra numarası

🎨 7️⃣ ListTile Özelleştirme

ListTile(
  leading: Icon(Icons.person),
  title: Text("Ahmet"),
  subtitle: Text("Öğrenci"),
  trailing: Icon(Icons.arrow_forward),
)
Özellik        Açıklama
leading        Soldaki ikon
title        Ana yazı
subtitle        Alt yazı
trailing        Sağdaki ikon

8️⃣ Tıklanabilir Liste

ListTile(
  title: Text(meyveler[index]),
  onTap: () {
    print("${meyveler[index]} seçildi");
  },
)

🔄 9️⃣ Dinamik Liste (StatefulWidget)

Liste değişiyorsa StatefulWidget kullanılır.

➕ Eleman Ekleme Örneği

class ListeOrnek extends StatefulWidget {
  @override
  _ListeOrnekState createState() => _ListeOrnekState();
}

class _ListeOrnekState extends State<ListeOrnek> {
  List<String> meyveler = ["Elma", "Armut"];

  void meyveEkle() {
    setState(() {
      meyveler.add("Yeni Meyve");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Dinamik Liste")),
      body: ListView.builder(
        itemCount: meyveler.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(meyveler[index]),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: meyveEkle,
        child: Icon(Icons.add),
      ),
    );
  }
}

🗑️ 1️⃣0️⃣ Eleman Silme

onTap: () {
  setState(() {
    meyveler.removeAt(index);
  });
}

🏆 1️⃣1️⃣ Gerçek Proje Örneği (Öğrenci Listesi)

class Ogrenci {
  String ad;
  int yas;

  Ogrenci(this.ad, this.yas);
}

Liste:

List<Ogrenci> ogrenciler = [
  Ogrenci("Ali", 15),
  Ogrenci("Ayşe", 16),
];

Builder:

ListView.builder(
  itemCount: ogrenciler.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(ogrenciler[index].ad),
      subtitle: Text("Yaş: ${ogrenciler[index].yas}"),
    );
  },
)

⚡ 1️⃣2️⃣ Önemli Kavramlar

KavramAnlamı
List        Veri tutar
ListView        Listeyi ekranda gösterir
builder        Performanslı liste üretir
setState        Ekranı yeniler
index        Sıra numarası

🎯 Sonuç

Flutter’da liste konusu:

  • 🔹 Veri tutma (List)

  • 🔹 Ekrana yazdırma (ListView)

  • 🔹 Dinamik güncelleme (StatefulWidget)

  • 🔹 Performans (ListView.builder)

mantığını öğrenmek demektir.




🎨 Flutter’da Modern Material 3 Liste Tasarımı

1️⃣ Material 3 Nedir?

Material 3 (Material You), Google’ın yeni tasarım sistemidir.

Özellikleri:

  • Daha yuvarlak köşeler

  • Dinamik renk sistemi

  • Daha modern butonlar

  • Soft gölgeler

  • Daha sade AppBar

Flutter’da aktif etmek için:

theme: ThemeData(
  useMaterial3: true,
),

🏗️ 2️⃣ Modern Liste Uygulaması (Görev Listesi Örneği)

Aşağıdaki örnekte:

✅ Material 3 aktif
✅ Modern Card tasarım
✅ Checkbox
✅ Silme butonu
✅ FloatingActionButton
✅ Soft shadow + yuvarlak köşe


📦 TAM ÇALIŞAN KOD

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,
        colorSchemeSeed: Colors.blue,
        brightness: Brightness.light,
      ),
      home: const ModernListe(),
    );
  }
}

class Gorev {
  String baslik;
  bool tamamlandi;

  Gorev(this.baslik, {this.tamamlandi = false});
}

class ModernListe extends StatefulWidget {
  const ModernListe({super.key});

  @override
  State<ModernListe> createState() => _ModernListeState();
}

class _ModernListeState extends State<ModernListe> {
  final List<Gorev> gorevler = [
    Gorev("Flutter çalış"),
    Gorev("Matematik tekrar et"),
    Gorev("Spor yap"),
  ];

  void gorevEkle() {
    setState(() {
      gorevler.add(Gorev("Yeni Görev"));
    });
  }

  void gorevSil(int index) {
    setState(() {
      gorevler.removeAt(index);
    });
  }

  void gorevDurumDegistir(int index, bool? value) {
    setState(() {
      gorevler[index].tamamlandi = value!;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Modern Görev Listesi"),
        centerTitle: true,
      ),
      body: ListView.builder(
        padding: const EdgeInsets.all(16),
        itemCount: gorevler.length,
        itemBuilder: (context, index) {
          final gorev = gorevler[index];

          return Card(
            elevation: 2,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20),
            ),
            margin: const EdgeInsets.only(bottom: 16),
            child: ListTile(
              contentPadding: const EdgeInsets.symmetric(
                  horizontal: 20, vertical: 10),
              leading: Checkbox(
                value: gorev.tamamlandi,
                onChanged: (value) =>
                    gorevDurumDegistir(index, value),
              ),
              title: Text(
                gorev.baslik,
                style: TextStyle(
                  fontSize: 18,
                  decoration: gorev.tamamlandi
                      ? TextDecoration.lineThrough
                      : null,
                ),
              ),
              trailing: IconButton(
                icon: const Icon(Icons.delete_outline),
                onPressed: () => gorevSil(index),
              ),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: gorevEkle,
        icon: const Icon(Icons.add),
        label: const Text("Ekle"),
      ),
    );
  }
}

3️⃣ Bu Tasarım Neden Modern?

ÖzellikNeden Modern?
useMaterial3: true        Yeni tasarım sistemi
colorSchemeSeed        Otomatik renk üretimi
RoundedRectangleBorder(20)        Yuvarlak köşe
FloatingActionButton.extended        Modern FAB
Soft elevation (2)        Yumuşak gölge

🎨 4️⃣ Renkleri Profesyonel Yapma

Eğer Healthy Living App gibi proje yapıyorsan şunu kullanabilirsin:

colorSchemeSeed: Colors.teal,

veya

colorScheme: ColorScheme.fromSeed(
  seedColor: Colors.deepPurple,
),

Bu otomatik olarak:

  • Primary

  • Secondary

  • Surface

  • Background

renklerini üretir.


🚀 5️⃣ Daha Profesyonel Görünüm İçin

Ekleyebileceğimiz gelişmiş özellikler:

✅ Search Bar (AppBar içine)
✅ Swipe ile silme (Dismissible)
✅ AnimatedContainer animasyonu
✅ BottomNavigationBar
✅ Dark Mode toggle
✅ Glassmorphism efekt
✅ Firebase bağlantılı modern liste




Süper Nuri 🚀
Şimdi sana Material 3 + Dark Mode (karanlık mod geçişi) olan modern ve profesyonel bir Flutter yapısını öğretiyorum.

Bu yapı:

✅ Material 3 aktif
✅ Light & Dark tema
✅ Tema değiştirme butonu
✅ Modern AppBar
✅ ColorScheme.fromSeed kullanımı
✅ Üretim kalitesinde yapı


🎨 1️⃣ Material 3 + Dark Mode Mantığı

Flutter’da karanlık mod için:

  • theme → Light tema

  • darkTheme → Dark tema

  • themeMode → Hangisi aktif?

Ama önemli nokta:

👉 Tema değişimini yönetmek için StatefulWidget kullanacağız.


🏗️ 2️⃣ Profesyonel Tema Yapısı

📦 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> {
  ThemeMode _themeMode = ThemeMode.light;

  void _toggleTheme() {
    setState(() {
      _themeMode =
          _themeMode == ThemeMode.light
              ? ThemeMode.dark
              : ThemeMode.light;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,

      // 🌞 Light Tema
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.teal,
          brightness: Brightness.light,
        ),
      ),

      // 🌙 Dark Tema
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.teal,
          brightness: Brightness.dark,
        ),
      ),

      themeMode: _themeMode,

      home: AnaSayfa(toggleTheme: _toggleTheme),
    );
  }
}

class AnaSayfa extends StatelessWidget {
  final VoidCallback toggleTheme;

  const AnaSayfa({super.key, required this.toggleTheme});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Material 3 Dark Mode"),
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.dark_mode),
            onPressed: toggleTheme,
          ),
        ],
      ),
      body: Center(
        child: Card(
          elevation: 3,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(24),
          ),
          child: Padding(
            padding: const EdgeInsets.all(30),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: const [
                Icon(Icons.nightlight_round, size: 50),
                SizedBox(height: 15),
                Text(
                  "Tema Değiştirilebilir",
                  style: TextStyle(fontSize: 20),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

3️⃣ Bu Yapı Neden Profesyonel?

ÖzellikSebep
StatefulWidget (MyApp)        Tema global yönetiliyor
ThemeMode        Light/Dark kontrol
ColorScheme.fromSeed        Otomatik modern renk
useMaterial3        Yeni tasarım sistemi
Rounded 24px Card        Modern UI

🎨 4️⃣ Healthy Living App İçin Öneri

Senin Healthy Living Tracker uygulamana bunu şöyle entegre edebiliriz:

  • 🌙 Kullanıcı tercihini SharedPreferences ile kaydetme

  • 📊 Dark mode’a özel grafik renkleri

  • 🥗 Soft yeşil tonlu sağlık teması

  • 🧠 Sistem temasını otomatik algılama (ThemeMode.system)


🚀 5️⃣ Daha Profesyonel Seviye

Bir üst seviyede:

✅ Tema animasyonlu geçiş
✅ Custom TextTheme
✅ Custom ElevatedButtonTheme
✅ Material 3 NavigationBar
✅ Dinamik renk (Android 12+)



Yorumlar

Bu blogdaki popüler yayınlar

Dart Uygulama Sınavı: Pardus ETAP 23 Kurulum Otomasyonu

Dart Programlama Dil Uygulama Sınavı Çalışma Soruları

Pardus Üzerinde Flutter Geliştirme Ortamı Kurulumu