↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar

3 dk okuma #flutter
Dizi · 10/61 Flutter Türkçe Tutorial
  1. Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
  2. Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
  3. Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
  4. Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
  5. Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
  6. Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
  7. Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
  8. Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
  9. Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
  10. Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
  11. Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
  12. Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
  13. Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
  14. Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
  15. Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
  16. Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
  17. Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
  18. Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
  19. Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
  20. Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
  21. Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
  22. Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
  23. Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
  24. Bölüm 6 — Konu 24: Provider Paketi
  25. Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
  26. Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
  27. Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
  28. Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
  29. Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
  30. Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
  31. Bölüm 7 — Konu 31: Deep Linking
  32. Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
  33. Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
  34. Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
  35. Bölüm 8 — Konu 35: Implicit Animasyonlar
  36. Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
  37. Bölüm 8 — Konu 37: Hero Animasyonları
  38. Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
  39. Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
  40. Bölüm 9 — Konu 40: Platform Channels
  41. Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
  42. Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
  43. Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
  44. Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
  45. Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
  46. Bölüm 10 — Konu 46: CI/CD
  47. Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
  48. Bölüm 10 — Konu 48: DevTools Profiling
  49. Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
  50. Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
  51. Bölüm 11 — Konu 51: Supabase Alternatifi
  52. Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
  53. Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
  54. Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
  55. Bölüm 12 — Konu 55: Flutter Web / Desktop
  56. Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
  57. Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
  58. Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
  59. Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
  60. Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
  61. Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
Dizinin sayfası →
İçindekiler 8 başlık
  1. MaterialApp — Uygulamanın Kök Widget'ı
  2. CupertinoApp — iOS Tarzı Alternatif
  3. Scaffold — Sayfa İskeleti
  4. AppBar — Üst Başlık Çubuğu
  5. Hepsini Bir Arada — İlk Gerçek Ekranımız
  6. SizedBox — Küçük Ama Sık Kullanılan Bir Widget
  7. 🎯 Bu Dersten Çıkarılması Gerekenler
  8. 📝 Ödevler

Bölüm 3'e hoş geldin. Şimdiye kadar tek widget'lık örnekler yazdık — bu derste, gerçek bir uygulamanın iskeletini kuracağız.

MaterialApp — Uygulamanın Kök Widget'ı

dart
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(
      title: 'İlk Uygulamam',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)),
      home: const AnaEkran(),
    );
  }
}

Not: theme: parametresine eskiden (Material 2 döneminde) doğrudan ThemeData(primarySwatch: Colors.blue) gibi tek bir renk veriliyordu. Bu hâlâ çalışır ama artık eski (legacy) bir kalıp — güncel Flutter (Material 3 varsayılan olduğu için) ColorScheme.fromSeed(seedColor: ...) kullanmanı bekler; tek bir "tohum" renkten tutarlı, tam bir renk paleti üretir. Tema sistemini bütün detaylarıyla Bölüm 4 Konu 16'da işleyeceğiz — burada sadece doğru/güncel sözdizimini görmen yeterli.

Bölüm 1 Konu 3'te bu kodu görmüştük ama detaylandırmamıştık — şimdi tam olarak işleyelim. MaterialApp, Google'ın Material Design tasarım diline uygun bir uygulama iskeleti kurar — Bölüm 1'de öğrendiğimiz Widget ağacının en tepesinde yer alır ve şu önemli işlevleri sağlar:

  • Tema yönetimi (theme:) — Bölüm 4'te tam olarak işleyeceğiz.
  • Navigasyon altyapısı (Navigator — Bölüm 3 Konu 14'te göreceğiz).
  • Yerelleştirme (localization) desteği.
  • home: — uygulamanın ilk açılan ekranını belirtir.

CupertinoApp — iOS Tarzı Alternatif

dart
import 'package:flutter/cupertino.dart';

CupertinoApp(
  home: CupertinoPageScaffold(
    child: Center(child: Text('iOS stili')),
  ),
)

CupertinoApp, Apple'ın iOS tasarım dili ("Cupertino", Apple'ın merkezinin bulunduğu şehir) kullanılarak tasarlanmış widget'lar sunar. Pratikte: Çoğu Flutter uygulaması MaterialApp kullanır — Material Design, hem Android hem iOS'ta iyi görünen, evrensel bir tasarım dilidir. CupertinoApp'i genelde, özellikle iOS'a özgü bir görünüm istediğinde veya belirli Cupertino widget'larını (örneğin CupertinoSwitch) kullanmak istediğinde tercih edersin. İkisini karıştırmak da mümkündür — bir MaterialApp içinde bazı Cupertino widget'ları kullanabilirsin.

Scaffold — Sayfa İskeleti

dart
Scaffold(
  appBar: AppBar(
    title: Text('Ana Sayfa'),
  ),
  body: Center(
    child: Text('Merhaba!'),
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
)

Scaffold, tek bir ekranın temel yapısını sağlayan bir widget'tır — Material Design'ın "sayfa şablonu" gibi düşünebilirsin. Bir uygulamada genelde her ekran (Bölüm 3 Konu 14'te göreceğimiz "sayfa" kavramı), kendi Scaffold'unu içerir.

Scaffold'un sunduğu temel "yuvalar" (slots):

  • appBar: üstteki başlık çubuğu.
  • body: ana içerik.
  • floatingActionButton: sağ altta yüzen aksiyon butonu.
  • bottomNavigationBar: alt navigasyon çubuğu (Bölüm 3 Konu 11'de listeler ile birlikte göreceğiz).
  • drawer: kenardan açılan menü.

Scaffold, aslında Bölüm 2 Konu 7'de öğrendiğimiz Container'a benzer bir "kompozisyon widget'ı" — arka planda, verdiğin bu parçaları (appBar, body vb.) doğru layout ile birleştiren bir widget'tır (Dart Bölüm 6'da öğrendiğimiz "named parametreler" mantığıyla, her "yuvayı" ayrı bir named parametre olarak alıyor).

AppBar — Üst Başlık Çubuğu

dart
AppBar(
  title: Text('Uygulamam'),
  backgroundColor: Colors.blue,
  actions: [
    IconButton(
      icon: Icon(Icons.search),
      onPressed: () {},
    ),
    IconButton(
      icon: Icon(Icons.more_vert),
      onPressed: () {},
    ),
  ],
)

actions, Bölüm 2'de öğrendiğimiz List<Widget> alan bir parametredir (Dart Bölüm 4'ü hatırla) — AppBar'ın sağ tarafında görünecek ikon butonlarını sıralar. IconButton'daki onPressed, Dart Bölüm 5'te öğrendiğimiz anonim fonksiyon (callback) kavramının doğrudan bir uygulaması — "bu butona tıklandığında çalışacak kod."

Hepsini Bir Arada — İlk Gerçek Ekranımız

dart
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(
      title: 'İlk Uygulamam',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const AnaEkran(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Ana Sayfa'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.flutter_dash, size: 80, color: Colors.blue),
            SizedBox(height: 16),
            Text('Flutter Öğreniyorum!', style: TextStyle(fontSize: 24)),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          print('Butona tıklandı');
        },
        child: Icon(Icons.favorite),
      ),
    );
  }
}

Dikkat et: AnaEkran, ayrı bir class olarak tanımlandı (Dart Bölüm 6'yı hatırla — tek sorumluluk prensibi, burada "uygulama iskeleti" ile "ana ekranın içeriği" ayrı class'lara bölünüyor). MyApp, sadece uygulama düzeyinde ayarları (tema, başlık) yönetirken, AnaEkran, gerçek ekran içeriğinden sorumlu.

SizedBox — Küçük Ama Sık Kullanılan Bir Widget

dart
SizedBox(height: 16) // sadece dikey boşluk
SizedBox(width: 8)   // sadece yatay boşluk

SizedBox, Bölüm 2 Konu 7'de öğrendiğimiz Padding'e benzer bir "tek iş yapan" widget'tır — sadece belirli bir boyutta boş alan oluşturur (bir Column/Row içinde iki widget arasına boşluk koymak için çok yaygın kullanılır). Padding'den farkı, Padding'in bir çocuğun etrafına boşluk eklemesi, SizedBox'ın ise kendi başına bir boşluk widget'ı olarak kullanılabilmesidir (child olmadan da).


🎯 Bu Dersten Çıkarılması Gerekenler

  • MaterialApp, uygulamanın kök widget'ıdır; tema, navigasyon altyapısı ve ilk ekranı (home) yönetir.
  • CupertinoApp, iOS tasarım diline uygun alternatif bir kök widget'tır.
  • Scaffold, tek bir ekranın temel yapısını (appBar, body, floatingActionButton gibi "yuvalarla") sağlar.
  • AppBar, üst başlık çubuğudur; actions ile sağ tarafa ikon butonları eklenebilir.
  • SizedBox, belirli boyutta boş alan oluşturmak için kullanılan basit bir widget'tır.

📝 Ödevler

  • [ ] AppBar, body ve FloatingActionButton içeren bir Scaffold iskeleti oluştur.
  • [ ] AppBar'a en az 2 actions ikonu ekle, her birine bir onPressed (şimdilik sadece print yazdıran) fonksiyonu bağla.
  • [ ] MyApp ve ayrı bir ekran class'ı (örn. AnaEkran) yaparak, uygulama düzeyi ayarlar ile ekran içeriğini birbirinden ayır.
  • [ ] SizedBox kullanarak bir Column içindeki widget'lar arasına dikey boşluklar ekle.
  • [ ] MaterialApp'i CupertinoApp ile değiştirip (basit bir örnekte), görsel farkı gözlemle.

Sıradaki konu: Bölüm 3 — Konu 11: ListView, GridView, SingleChildScrollView (+ Builder Pattern)