↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi

3 dk okuma #flutter
Dizi · 12/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 11 başlık
  1. Text — Temel Metin Widget'ı
  2. TextStyle — Metni Biçimlendirme
  3. copyWith() — Var Olan Bir Stili "Değiştirerek Kopyalama"
  4. Icon — Simgeler
  5. Image — Resim Gösterme
  6. Asset Yönetimi — Projeye Resim Ekleme
  7. Farklı Ekran Yoğunlukları İçin Asset'ler (Retina/HiDPI Desteği)
  8. AssetImage vs Image.asset — İnce Bir Fark
  9. Hepsini Bir Arada — Profil Kartı Örneği
  10. 🎯 Bu Dersten Çıkarılması Gerekenler
  11. 📝 Ödevler

Text — Temel Metin Widget'ı

dart
Text(
  'Merhaba Flutter',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
)

Text'i zaten önceki derslerde kullanmıştık — şimdi style parametresini derinlemesine görelim.

TextStyle — Metni Biçimlendirme

dart
TextStyle(
  fontSize: 18,
  fontWeight: FontWeight.w600, // 100-900 arası, w400 normal, w700 bold'a yakın
  fontStyle: FontStyle.italic,
  color: Colors.black87,
  letterSpacing: 1.2,
  height: 1.5, // satır yüksekliği (line-height) çarpanı
  decoration: TextDecoration.underline,
)

FontWeight, Dart Bölüm 7'de öğrendiğimiz enum'a çok benzer bir yapıdır (aslında FontWeight, sabit FontWeight.w100...w900 değerleri barındıran özel bir class'tır — enum'un biraz daha gelişmiş bir kuzeni). TextStyle'ın kendisi, Bölüm 2 Konu 5'te öğrendiğimiz immutable (değişmez) widget mantığına uygun tasarlanmıştır — bir TextStyle nesnesi oluşturduktan sonra değiştirilemez, yeni bir stil istiyorsan yeni bir TextStyle oluşturman gerekir.

copyWith() — Var Olan Bir Stili "Değiştirerek Kopyalama"

dart
TextStyle temelStil = TextStyle(fontSize: 16, color: Colors.black);

TextStyle kalinStil = temelStil.copyWith(fontWeight: FontWeight.bold);
// kalinStil: fontSize 16 (korundu), color siyah (korundu), fontWeight bold (değişti)

Bölüm 1 Konu 4'te (hot reload derste) .copyWith()'i kısaca kullanmıştık — şimdi bunun neden var olduğunu tam olarak anlıyoruz. TextStyle immutable olduğu için (final alanlar), var olan bir stili "temel alıp, sadece bir-iki özelliğini değiştirmek" istediğinde, tüm özellikleri tekrar yazmak zorunda kalmamak için copyWith() kullanılır — bu, sadece belirttiğin alanları değiştirir, belirtmediklerin aynı kalır.

Bilmen faydalı bir detay: copyWith(), Flutter'ın birçok immutable class'ında (TextStyle, EdgeInsets, ve ilerleyen bölümlerde göreceğin state yönetimi sınıflarında) tekrar eden bir kalıptır — bu, Dart Bölüm 6'da öğrendiğimiz method chaining/kompozisyon felsefesinin, "değişmez nesnelerle rahat çalışma" ihtiyacına verilen bir cevaptır.

Icon — Simgeler

dart
Icon(
  Icons.favorite,
  color: Colors.red,
  size: 32,
)

Icons, Flutter'ın Material Design ikon setine erişim sağlayan bir class'tır (Bölüm 1 Konu 3'te pubspec.yaml'da gördüğümüz uses-material-design: true ayarı, bu ikonların kullanılabilmesini sağlıyordu). Icons.favorite, Icons.search, Icons.home gibi binlerce hazır ikon mevcuttur.

Image — Resim Gösterme

Flutter'da resim göstermenin birkaç farklı kaynağı vardır:

dart
Image.network('https://ornek.com/resim.png') // internetten
Image.asset('assets/images/logo.png')         // proje içinden (asset)
Image.file(File('/yol/resim.png'))             // cihaz dosya sisteminden
Image.memory(Uint8List(...))                   // bellekte tutulan byte verisinden

Image.network, Bölüm 10'da (Dart) öğrendiğimiz Future/asenkron mantığı örtük olarak kullanır — resim internetten indirilene kadar, varsayılan olarak boş görünür (bunu Bölüm 5'te, loadingBuilder ile nasıl özelleştireceğini göreceğiz).

Asset Yönetimi — Projeye Resim Ekleme

Dart Bölüm 12 Konu 53'te pubspec.yaml'ı derinlemesine işlemiştik — şimdi assets bölümünü ekleyelim.

1. Adım — Klasör oluştur:

metin
proje_kökü/
  assets/
    images/
      logo.png

2. Adım — pubspec.yaml'da tanımla:

yaml
flutter:
  uses-material-design: true
  assets:
    - assets/images/logo.png
    # veya tüm klasörü dahil etmek için:
    - assets/images/

3. Adım — Kodda kullan:

dart
Image.asset('assets/images/logo.png')

Kritik nokta: pubspec.yaml'a asset ekledikten sonra, hot reload yeterli değildir — Dart Bölüm 12'de öğrendiğimiz pubspec.yaml değişikliklerinde olduğu gibi, pubspec.yaml her değiştiğinde hot restart (Bölüm 1 Konu 4'ü hatırla) veya flutter pub get + yeniden çalıştırma gerekir. Bunun nedeni, asset listesinin, uygulamanın derlenme sürecinin bir parçası olarak "paketlenmesi" gerekmesidir — bu, JIT ile anlık güncellenebilecek bir kod değişikliği değil, yapılandırma değişikliğidir.

Farklı Ekran Yoğunlukları İçin Asset'ler (Retina/HiDPI Desteği)

metin
assets/
  images/
    logo.png       # 1x (temel çözünürlük)
    2.0x/
      logo.png     # 2x çözünürlük (yüksek DPI ekranlar için)
    3.0x/
      logo.png     # 3x çözünürlük

Flutter, cihazın ekran yoğunluğuna göre otomatik olarak doğru çözünürlükteki resmi seçer — sen kodda hep Image.asset('assets/images/logo.png') yazarsın, Flutter arka planda cihaza uygun olanı bulur. Bu, mobil geliştirmede yaygın bir kalıptır (web'deki srcset mantığına benzer).

AssetImage vs Image.asset — İnce Bir Fark

dart
Image.asset('assets/images/logo.png') // widget - doğrudan ekranda görünür

// AssetImage - bir "resim kaynağı" tanımı, kendisi widget DEĞİL
CircleAvatar(
  backgroundImage: AssetImage('assets/images/logo.png'),
)

Image.asset(...), aslında arka planda Image(image: AssetImage(...)) şeklinde çalışır — yani Image.asset, kolaylık sağlayan bir kısayol constructor'dır (Dart Bölüm 6 Konu 27'de öğrendiğimiz named constructor kavramının, Flutter'ın kendi kütüphanesindeki bir örneği!). AssetImage, bazı widget'ların (örneğin CircleAvatar, DecorationImage) Image widget'ı değil, resim kaynağı beklediği durumlarda kullanılır.

Hepsini Bir Arada — Profil Kartı Örneği

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

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          radius: 30,
          backgroundImage: AssetImage('assets/images/profil.png'),
        ),
        SizedBox(width: 12),
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Ahmet Yılmaz',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            Row(
              children: [
                Icon(Icons.star, color: Colors.amber, size: 16),
                Text(' 4.8'),
              ],
            ),
          ],
        ),
      ],
    );
  }
}

🎯 Bu Dersten Çıkarılması Gerekenler

  • TextStyle, immutable bir stil tanımıdır; .copyWith(), var olan bir stili temel alıp belirli alanları değiştirerek yeni bir stil oluşturur.
  • Icon, Icons class'ı üzerinden Material Design ikonlarına erişim sağlar.
  • Image.network/asset/file/memory, farklı kaynaklardan resim göstermenin yollarıdır.
  • Asset'ler pubspec.yaml'da tanımlanmalı ve değişikliklerden sonra hot restart (veya yeniden çalıştırma) gerekir.
  • Image.asset, aslında Image(image: AssetImage(...))'in kısayoludur — Flutter'ın kendi kütüphanesinde named constructor kullanımına bir örnek.

📝 Ödevler

  • [ ] Farklı TextStyle özellikleriyle (fontSize, fontWeight, color, letterSpacing) bir metin oluştur.
  • [ ] copyWith() kullanarak, temel bir stili temel alıp sadece rengini değiştiren yeni bir stil oluştur.
  • [ ] Projene bir resim ekle (assets klasörüne), pubspec.yaml'da tanımla, Image.asset ile göster.
  • [ ] Image.network ile internetten bir resim göster.
  • [ ] Konu 12'deki "ProfilKarti" örneğine benzer, kendi tasarladığın bir profil widget'ı yaz (CircleAvatar + isim + ikon içersin).

Sıradaki konu: Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)