# 2. Hafta - Widget Ağacı ve MaterialApp

## Uygulama hedefi

Bu derste **Tanıtım Ekranı** uygulamasını sıfırdan kuracağız. Ekranı tek parça olarak düşünmek yerine kök, sayfa, yerleşim ve içerik widget'larına ayıracağız. Ders sonunda öğrenci gördüğü bir ekranı widget ağacı biçiminde okuyabilecek.

## Kazanımlar

- `runApp` ile kök widget arasındaki ilişkiyi açıklar.
- `MaterialApp`, `Scaffold`, `AppBar` ve `body` görevlerini ayırt eder.
- İçeriği `ListView`, `Card`, `Column`, `Wrap` ve `Chip` ile düzenler.
- Sabit ekran için `StatelessWidget` kullanır.
- Uzun içeriğin küçük ekranda taşmasını `ListView` ile önler.

## Widget ağacını okumak

Tanıtım Ekranı'nın sadeleştirilmiş ağacı şöyledir:

```text
TanitimApp
└── MaterialApp
    └── TanitimPage
        └── Scaffold
            ├── AppBar
            └── ListView
                ├── CircleAvatar
                ├── Text
                ├── Card
                ├── Wrap
                │   └── Chip × 3
                └── FilledButton
```

Girinti arttıkça widget'ın başka bir widget'ın çocuğu olduğu anlaşılır. `MaterialApp` uygulama düzeyindeki tema ve temel davranışları, `Scaffold` ise tek sayfanın görsel çatısını yönetir.

## 1. Uygulamayı başlatma

```dart
void main() => runApp(const TanitimApp());

class TanitimApp extends StatelessWidget {
  const TanitimApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
    debugShowCheckedModeBanner: false,
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: const Color(0xff00695c),
      ),
      useMaterial3: true,
    ),
    home: const TanitimPage(),
  );
}
```

Bu ekranda kullanıcı tarafından değiştirilen bir veri olmadığı için `StatelessWidget` yeterlidir.

## 2. Kaydırılabilir sayfa oluşturma

```dart
Scaffold(
  appBar: AppBar(title: const Text('Tanıtım Ekranı')),
  body: ListView(
    padding: const EdgeInsets.all(22),
    children: const [
      CircleAvatar(
        radius: 52,
        child: Icon(Icons.person, size: 62),
      ),
      SizedBox(height: 14),
      Text('Ece Yılmaz', textAlign: TextAlign.center),
    ],
  ),
)
```

`ListView`, ekran yüksekliği yetersiz olduğunda içeriği kaydırır. Sabit bir `Column` kullanılsaydı küçük ekranda sarı-siyah taşma uyarısı oluşabilirdi.

## 3. Beceri etiketlerini yerleştirme

```dart
const Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    Chip(avatar: Icon(Icons.flutter_dash), label: Text('Flutter')),
    Chip(avatar: Icon(Icons.code), label: Text('Dart')),
    Chip(avatar: Icon(Icons.palette), label: Text('Tasarım')),
  ],
)
```

`Wrap`, yatay alan bittiğinde sonraki Chip'i yeni satıra taşır. Bu nedenle farklı telefon genişliklerinde daha güvenlidir.

## Çalışan uygulama

Uygulama gerçek Flutter widget testinde 430 × 760 ekran boyutunda çalıştırıldı. Test; Hakkımda bölümünü, Flutter beceri etiketini ve widget ağacının oluşturulmasını doğruladı.

![Tanıtım Ekranı çalışan Flutter uygulaması](../../screenshots/week-02-adapted.png)

Proje klasörü: `Uygulamalar/Uygulama-02-Tanıtım Ekranı`

## Uygulama çalışması

1. Öğrenci adını ve sınıf bilgisini değiştirin.
2. En az dört beceri Chip'i ekleyin.
3. `Wrap` yerine `Row` kullanıp dar ekranda oluşan farkı gözlemleyin.
4. Hakkımda kartını ayrı bir widget sınıfına çıkarın.
5. Ekranı 320 ve 430 piksel genişliklerde test edin.

## Özgün proje - Günlük Hedef

Bu projede widget ağacına durum yönetimi eklenir. Üç günlük hedef Checkbox ile işaretlenir; tamamlanan hedef sayısı ve `LinearProgressIndicator` değeri aynı listeden hesaplanır. “Tümünü tamamla” düğmesi bütün hedefleri gerçek zamanlı günceller.

![Günlük Hedef çalışan özgün Flutter uygulaması](../../screenshots/week-02-original.png)

### Öğrenci görevi

En az üç hedef içeren kendi takip ekranınızı oluşturun. Checkbox değiştiğinde sayaç ve ilerleme çubuğu birlikte güncellenmelidir. Çözümünüzü gönderdikten sonra sistemde **Günlük Hedef gerçek Dart çözümü** ve indirilebilir çalışan proje açılacaktır.

### Geri bildirim ölçütleri

- Hedef metni ile tamamlanma durumu aynı sıra numarasıyla eşleşiyor.
- Tamamlanan sayı listeden hesaplanıyor; elle sabitlenmiyor.
- Sıfıra bölme ihtimali engelleniyor.
- Checkbox ve toplu tamamlama işlemleri `setState` içinde çalışıyor.
- Son görüntü checkbox animasyonu tamamlandıktan sonra alınıyor.

## Ders sonu kontrolü

- Widget ağacını yukarıdan aşağı okuyabiliyorum.
- MaterialApp ve Scaffold görevlerini ayırt edebiliyorum.
- Dar ekranda ListView ve Wrap kullanma nedenini açıklayabiliyorum.
- Stateless ve Stateful ekran seçimini gerekçelendirebiliyorum.
- Çalışan Flutter uygulamasını test ederek doğrulayabiliyorum.
