Mobil Programlama Flutter'a Giriş PDF
Document Details
Uploaded by RighteousBandoneon
Elyase İskender
Tags
Summary
Bu belge, Google tarafından geliştirilen açık kaynaklı bir UI geliştirme kiti olan Flutter platformuna genel bir giriş sunmaktadır. Mobil, web ve masaüstü uygulamalar için tek bir kod tabanı kullanarak yüksek performanslı, kullanıcı dostu ve zengin arayüzler oluşturmaya olanak sağlamaktadır. Dart programlama diliyle desteklenmektedir.
Full Transcript
Mobil Programlama Flutter'a Giriş Dr. Öğretim Üyesi Elyase İskender Yönetim Bilişim Sistemleri 1. Flutter Nedir? 2. Flutter Neden Geliştirildi? 3. Flutter'ın Geleceği İçindekiler 4. Flutter Topluluğu ve Ka...
Mobil Programlama Flutter'a Giriş Dr. Öğretim Üyesi Elyase İskender Yönetim Bilişim Sistemleri 1. Flutter Nedir? 2. Flutter Neden Geliştirildi? 3. Flutter'ın Geleceği İçindekiler 4. Flutter Topluluğu ve Katkıları 5. İlk Flutter Projeniz 6. Widget’lar – Flutter’ın Yapı Taşları 7. Flutter Uygulamasını Geliştirme ve Çalıştırma - Flutter, Google tarafından geliştirilmiş açık kaynak kodlu bir UI geliştirme kitidir. - Mobil, web ve masaüstü 1. Flutter platformlar için tek bir kod tabanı ile natively derlenmiş Nedir? uygulamalar oluşturur. - Yüksek performanslı, kullanıcı dostu ve zengin arayüzler oluşturmak için ideal bir araçtır. - Mobil platformlarda tek bir kod tabanı ile çoklu platform desteği sağlamak. 2. Flutter - Var olan çapraz platform çözümlerine kıyasla daha Neden yüksek performans ve daha iyi Geliştirildi? kullanıcı deneyimi sunmak. - Geliştirme sürecini hızlandırmak ve geliştiricilere daha esnek bir ortam sunmak. - Flutter’ın gelecek sürümlerinde daha fazla platform (Windows, macOS) desteği. 3. Flutter'ın - Topluluk katkıları ile yeni widget’lar ve geliştirme Geleceği araçlarının eklenmesi. - Performans iyileştirmeleri ve daha geniş donanım entegrasyonu. - Flutter topluluğu, dünyanın dört bir yanındaki geliştiriciler tarafından aktif olarak desteklenmektedir. 4. Flutter - Topluluk desteği ile Topluluğu ve zenginleştirilmiş kütüphaneler, paketler ve eklentiler. Katkıları - Geliştirici konferansları, eğitimler ve atölyeler ile bilgi paylaşımı. 5. İlk Flutter Projeniz - Flutter SDK ve Dart kurulumu. - Yeni bir proje oluşturma (`flutter create proje_adi`). - Proje yapısının incelenmesi: `lib` klasörü, `main.dart` dosyası ve `pubspec.yaml`. - İlk "Hello World" uygulamanızı geliştirin. 6. Widget’lar – Flutter’ın Yapı Taşları - Flutter’da her şey bir widgettır: Text, Image, Container, Row, Column. - StatelessWidget ve StatefulWidget farkları. - Kullanıcı etkileşimleri ve dinamik UI oluşturma. Windows Üzerinde Flutter Geliştirme Ortamı Kurulumu Flutter SDK, PowerShell, Visual Studio ve Android Studio Kurulumu İçindekiler 1. Geliştirici Modunu Etkinleştirme 2. PowerShell Yükleme ve Güncelleme 3. Git Yükleme 4. Visual Studio ve Android Studio Yükleme 5. Flutter SDK Kurulumu 6. Flutter Kurulumunun Doğrulanması 1. Geliştirici Modunu Etkinleştirme - Ayarlar uygulamasını açın ve “Geliştirici Modu”nu etkinleştirin. - Windows 10: “Güncelleştirme ve Güvenlik” altında “Geliştiriciler için” sekmesini seçin. - Windows 11: “Gizlilik ve Güvenlik” altında “Geliştirici Modu” seçeneğini açın. 2. PowerShell - PowerShell’i güncellemek için: https://aka.ms/powershell-release?tag=stable Yükleme ve adresinden en son sürümü indirin. - İndirilen `.msi` dosyasını çalıştırın ve kurulumu Güncelleme tamamlayın. - `pwsh` komutunu kullanarak PowerShell’i doğrulayın. 3. Git Yükleme - [Git İndirme Sayfası](https://git-scm.com/downloads) adresinden uygun sürümü indirin. - İndirilen dosyayı çalıştırın ve kurulum işlemini tamamlayın. - “Git Bash” yazarak kurulumun doğruluğunu kontrol edin. 4. Visual Studio ve Android Studio Yükleme - Visual Studio Community sürümünü indirerek “.NET Masaüstü Geliştirme” iş yükünü seçin. - Android Studio’yu indirerek SDK, Emulator ve gerekli bileşenleri ekleyin. 5. Flutter SDK Kurulumu - Flutter SDK’yı [Flutter İndirme Sayfası](https://docs.flutter.dev/get- started/install/windows) adresinden indirin. - İndirilen zip dosyasını `C:\src` gibi bir dizine çıkarın. - `C:\src_x000C_lutter_x0008_in` dizinini PATH değişkenine ekleyin. 6. Flutter Kurulumunun Doğrulanması - Komut satırını veya PowerShell’i açın. - `flutter doctor` komutunu çalıştırarak kurulumu doğrulayın. flutter doctor -–android-licenses - Eksik bileşenleri tamamladıktan sonra `flutter doctor` tekrar çalıştırarak kontrol edin. 7. Flutter Uygulamasını Geliştirme ve Çalıştırma flutter create hello_world `flutter run` komutu ile uygulamanızı çalıştırın. - Emulator veya fiziksel cihazda testi. - Hot Reload ile anlık güncellemeler. Flutter Proje Yapısı Flutter Proje Dosya ve Klasör Yapısının İncelenmesi 1. Platforma Özgü Klasörler 2. `hello_world.iml` Dosyası 3. `.idea` ve `.vscode` Klasörleri 4. `lib` Klasörü 5. `pubspec.yaml` ve İçindekiler `pubspec.lock` Dosyaları 6. `README.md` Dosyası 7. `test` Klasörü 8. `analysis_options.yaml` Dosyası 1. Platforma Özgü Klasörler - `android/` ve `ios/`: Platforma özgü kodları içerir. Android için Java veya Kotlin, iOS için Swift veya Objective-C kullanılır. - `linux/`, `macos/`, `web/` ve `windows/`: Flutter’ın desteklediği diğer platformlar için kodları içerir. - Her platform klasöründe ilgili platformun yapılandırma dosyaları ve bağımlılıkları yer alır. 2. `hello_world.iml` Dosyası - IntelliJ IDEA ve Android Studio tarafından kullanılan proje dosyasıdır. - Java modül bilgilerini içerir ve proje ayarlarını yönetir. - `.idea`: IntelliJ IDEA ve Android Studio proje ayarlarını içerir. 3. `.idea` ve - `.vscode`: Visual Studio `.vscode` Code için yapılandırma Klasörleri dosyalarını içerir. - Bu klasörler, proje IDE yapılandırmaları için kullanılır. - Flutter uygulamalarının ana geliştirme klasörüdür. 4. `lib` - Varsayılan olarak `main.dart` dosyası içerir. Klasörü - `main.dart` dosyası, uygulamanın giriş noktasıdır ve uygulamanın başlatılmasını sağlayan `void main()` fonksiyonunu içerir. - `pubspec.yaml`: Proje bağımlılıklarını, resim 5. dosyalarını, yazı tiplerini ve `pubspec.yaml` ve diğer kaynakları tanımlar. `pubspec.lock` Dosyaları - `pubspec.lock`: Bağımlılıkların kilit dosyasıdır ve bağımlılıkların sürüm bilgilerini içerir. - Projenin dökümantasyonu için kullanılan standart 6. bir dosyadır. `README.md` Dosyası - Projenin nasıl kurulacağı ve kullanılacağı hakkında bilgi verir. - Test dosyalarının yer aldığı klasördür. - Birim ve widget testleri 7. `test` burada bulunur. Klasörü - Kod kalitesini ve güvenliğini sağlamak için testler önemlidir. - Kod analizörünü yapılandırmak için kullanılır. - Kodlama standartlarını 8. tanımlar ve proje genelinde `analysis_options.yaml` Dosyası aynı stil kurallarını sağlar. - `linter` aracı ile birlikte kullanılır ve yaygın hataların bulunmasını sağlar. Dart Programlama Dili ve Flutter İçin Önemi Dart'ın Geçmişi, Özellikleri ve Flutter'daki Rolü 1. Dart'ın Tarihi 2. Flutter'ın Dart'ı Seçme Nedenleri 3. Dart ve Flutter'ın Performans Avantajları 4. Dart'ın Kolay İçindekiler Öğrenilebilirliği 5. Deklaratif Kullanıcı Arayüzü ve Dart'ın Rolü 6. Dart ile Layout ve Stil Yönetimi - Dart, Google tarafından 2011 yılında tanıtıldı ve 2013'te ilk stabil sürümü yayımlandı. - JavaScript’e alternatif olarak web geliştirme 1. Dart'ın amacıyla geliştirilmiş olsa da, Tarihi başlangıçta beklenen ilgiyi görmedi. - Flutter ile birlikte Dart’ın kullanımı hızla artış gösterdi ve popüler bir programlama dili haline geldi. - Flutter, yüksek performans ve hızlı geliştirme deneyimi sunmayı 2. Flutter'ın hedefliyordu. - Dart, bu hedeflere Dart'ı ulaşmak için uygun bir programlama Seçme dili olarak seçildi: - **AOT (Ahead- Nedenleri of-Time) Derleme:** Üretim ortamında yüksek performans. - **JIT (Just-in- Time) Derleme:** Geliştirme sürecinde hızlı geri bildirim. - Dart, AOT derleme yöntemi ile üretim 3. Dart ve ortamında hızlı uygulamalar sağlar. Flutter'ın - JIT derleme ile geliştirme Performans sürecinde hızlı geri bildirim alarak Avantajları hataları hızlıca düzeltebilirsiniz. - Dart’ın kilitsiz çöp toplama mekanizması (garbage collection) yüksek performans sunar. 4. Dart'ın Kolay Öğrenilebilirliği - Dart, modern ve esnek bir dil olup, hem dinamik hem de statik dillere aşina olan geliştiriciler için uygundur. - Nesne yönelimli (OOP) yapısı ve zengin kütüphane desteği ile hızlıca uygulama geliştirmeye olanak tanır. - Topluluk desteği ve zengin dokümantasyonu sayesinde öğrenmesi kolay bir dildir. 5. Deklaratif Kullanıcı Arayüzü ve Dart'ın Rolü - Deklaratif UI, Flutter'da UI bileşenlerinin sadece bir "taslak" (blueprint) olarak ele alınmasını sağlar. - UI değişiklikleri, ilgili widget’ın ve alt bileşenlerinin yeniden oluşturulması ile gerçekleştirilir. - Bu yaklaşım, UI yönetimini daha güvenli ve düzenli hale getirir. 6. Dart ile Layout ve Stil Yönetimi - Dart, layout ve stil yönetimi için tek bir sözdizimi kullanır. - Bu, geliştiricilerin UI ve stil özelliklerini farklı diller öğrenmek zorunda kalmadan yönetebilmesini sağlar. - Flutter ve Dart, geliştirici bilişsel yükünü azaltır ve verimliliği artırır. Flutter ve Tek Kod Tabanının Avantajları Tek Kod Tabanı ile Yüksek Performanslı Mobil Uygulamalar Geliştirme İçindekiler 1. Tek Kod Tabanının Avantajları 2. Diğer Çerçevelerin Zayıf Yönleri 3. Flutter Bu Sorunları Nasıl Çözüyor? - Birden fazla dil öğrenme zorunluluğu ortadan kalkar. 1. Tek Kod - Uzun ve daha maliyetli Tabanının geliştirme döngülerinin Avantajları önüne geçilir. - Farklı platformlarda tutarsızlık sorunları minimize edilir. - Performans sorunları: Web view kullanımı, düşük performans ve kötü kullanıcı deneyimi. 2. Diğer - Tasarım kısıtlamaları: Mobil Çerçevelerin deneyim için optimize edilmemiş Zayıf Yönleri diller. - Tam anlamıyla tek kod tabanı olmaması: Platforma özgü kod yazma ihtiyacı. - Yüksek performans: Flutter, platforma özgü kod ile çalışarak hızlı uygulamalar sağlar. 3. Flutter Bu Sorunları - Modern ve esnek tasarım: Nasıl Mobil deneyim için optimize Çözüyor? edilmiştir. - Gerçek tek kod tabanı: Minimum platforma özgü kod ile çapraz platform geliştirme. Flutter ve Yerel (Native) Uygulamalar Arasında Çift Yönlü İletişim Flutter ile Yerel Kod Arasında Veri ve İşlev İletişimi 1. Çift Yönlü İletişim Nedir? 2. Platform Kanalları ile İletişim 3. Flutter’ın Performans Avantajları İçindekiler 4. Flutter’ın UI Üzerindeki Kontrolü 5. Açık Kaynak ve Topluluk Desteği 6. Geliştirici Araçları ve Kaynaklar 1. Çift Yönlü İletişim Nedir? - Flutter, yerel kod ile veri ve işlev paylaşımına olanak sağlar. - Bu sayede, Flutter bileşenlerini yerel bir uygulamaya entegre edebilir veya yerel bileşenleri Flutter uygulamanızda kullanabilirsiniz. - Platform kanalları, yöntem kanalları ve olay kanalları ile bu iletişim gerçekleştirilir. 2. Platform Kanalları ile İletişim - Flutter ile yerel kod arasında veri ve işlev çağrısı yapabilmek için platform kanalları kullanılır. - Platform kanalları: Flutter'dan yerel koda veya yerel koddan Flutter'a veri göndermek için kullanılır. - Yöntem kanalları: Flutter ve yerel kod arasında fonksiyon çağrıları gerçekleştirilir. - Olay kanalları: Yerel koddan Flutter'a asenkron veri gönderimi sağlar. - Flutter, grafik işlem motoru (Skia) kullanarak tüm UI bileşenlerini doğrudan render eder. 3. Flutter’ın - Dart’ın AOT derleyicisi ile yerel Performans kod oluşturur, bu sayede yüksek performans sunar. Avantajları - Ekstra katman veya OS API çağrısı olmadan doğrudan pixel işlemi yapar. - Flutter, tüm görsel bileşenleri kendi API'si üzerinden yönetir ve cihaz üzerindeki tüm pikselleri kontrol 4. eder. Flutter’ın - Platforma özgü UI kitleri (Material UI ve Cupertino) ile iOS ve Android'de yerel görünüm sunar. Üzerindeki Kontrolü - Karmaşık ve performanslı arayüzler için esnek bir yapı sağlar. - Google tarafından 5. Açık desteklenen açık kaynak bir proje olarak, Flutter geniş bir Kaynak topluluk desteğine sahiptir. ve - Topluluk katkıları ile hata Topluluk düzeltmeleri, yeni özelliklerin Desteği eklenmesi ve dokümantasyon geliştirilir. - Geliştiricilere yönelik zengin dokümantasyon ve eğitim 6. kaynakları. Geliştirici - IDE entegrasyonları (Android Araçları Studio, IntelliJ, VS Code) ve komut satırı araçları ile verimli geliştirme. ve - Hot Reload ve `flutter doctor` Kaynaklar komutları ile hızlı geliştirme ve kurulum desteği. Dart Programlamaya Giriş Dr. Öğretim Üyesi Elyase İskender Yönetim Bilişim Sistemleri Dart Programlama: Değişken Türleri Dart Değişkenlerine Giriş Dart, dinamik ve statik tür bildirimi destekler. Değişkenler tamsayılar, ondalıklı sayılar, metinler ve daha fazlasını saklayabilir. int: Tam Sayı Türü 'int' türü tam sayıları temsil eder. Örnek: int yas = 25; print(yas); // Çıktı: 25 double: Ondalıklı Sayı Türü 'double' türü ondalıklı sayıları temsil eder. Örnek: double boy = 1.75; print(boy); // Çıktı: 1.75 String: Metin Türü 'String' türü metin verilerini temsil eder. Örnek: String ad = 'Fahri'; print(ad); // Çıktı: Fahri bool: Mantıksal Değer Türü 'bool' türü mantıksal bir değeri temsil eder, true veya false. Örnek: bool ogrenciMi = true; print(ogrenciMi); // Çıktı: true List: Elemanlar Dizisi 'List' türü sıralı bir elemanlar dizisini temsil eder. Örnek: List sayilar = [1, 2, 3, 4]; print(sayilar); // Çıktı: [1, 2, 3, 4] Map: Anahtar-Değer Çiftleri 'Map' türü anahtar-değer çiftlerini temsil eder. Örnek: Map notlar = {'Matematik': 95, 'İngilizce': 85}; print(notlar); // Çıktı: {Matematik: 95, İngilizce: 85} dynamic: Esnek Tür Tanımlama 'dynamic' türü, esnek bir tür tanımlamasına olanak tanır ve tür çalışma zamanında belirlenir. Örnek: dynamic deger = 100; deger = 'Dart Programlama'; print(deger); // Çıktı: Dart Programlama Dart Programlama: Kontrol Akışı Kontrol Akışı Nedir? Kontrol akışı, bir programın çalıştırma sırasını belirleyen yapılardır. Dart'ta kontrol akışı if-else, switch-case, döngüler ve daha fazlasıyla sağlanır. if-else Yapıları 'if' yapısı, bir koşulun doğru olup olmadığını kontrol eder. Örnek: int number = 10; if (number > 0) { print('Number is positive'); } else { print('Number is not positive'); } else-if Yapısı 'else if' birden fazla koşul kontrol etmek için kullanılır. Örnek: int score = 75; if (score >= 90) { print('A grade'); } else if (score >= 75) { print('B grade'); } else { print('C grade'); } Switch-Case Yapısı 'switch-case' yapısı, bir değişkenin belirli değerlere göre çalışmasını sağlar. Örnek: String grade = 'B'; switch (grade) { case 'A': print('Excellent'); break; case 'B': print('Good'); break; default: print('Invalid grade'); } For Döngüsü 'for' döngüsü, belirli bir sayıda tekrar eden işlemler için kullanılır. Örnek: for (int i = 0; i < 5; i++) { print('Dart is awesome!'); } For-in Döngüsü 'for-in' döngüsü, bir koleksiyonun her bir elemanını dolaşmak için kullanılır. Örnek: List fruits = ['Apple', 'Banana', 'Mango']; for (var fruit in fruits) { print(fruit); } While Döngüsü 'while' döngüsü, bir koşul doğru olduğu sürece kod bloğunu tekrar eder. Örnek: int count = 0; while (count < 3) { print('Counting: \$count'); count++; } Do-While Döngüsü 'do-while' döngüsü, koşul yanlış olsa bile en az bir kez çalışır. Örnek: int i = 0; do { print('This runs at least once'); i++; } while (i < 1); Break ve Continue 'break' döngüyü anında sonlandırır, 'continue' ise mevcut adımı atlar. Örnek: for (int i = 0; i < 5; i++) { if (i == 3) { break; } print(i); // 0, 1, 2 } for (int i = 0; i < 5; i++) { if (i == 3) { continue; } print(i); // 0, 1, 2, 4 } Dart Programlama: Fonksiyonların Uygulanması Fonksiyon Nedir? Fonksiyonlar, belirli bir görevi yerine getiren kod bloklarıdır. Fonksiyonlar, kodun yeniden kullanılabilirliğini sağlar ve belirli bir işlevi yerine getirir. Basit Fonksiyon Tanımlama Dart'ta fonksiyon tanımlamak için 'returnType functionName()' yapısı kullanılır. Örnek: void sayHello() { print('Hello, World!'); } Parametre Alan Fonksiyonlar Bir fonksiyona parametreler ekleyerek daha esnek hale getirebiliriz. Örnek: void greet(String name) { print('Hello, \$name!'); } greet('Fahri'); // Çıktı: Hello, Fahri! Geri Dönüş Değeri Olan Fonksiyonlar Fonksiyonlar bir işlem yaptıktan sonra değer döndürebilirler. Örnek: int add(int a, int b) { return a + b; } int result = add(5, 3); print(result); // Çıktı: 8 Varsayılan Parametreler Dart'ta fonksiyonlar varsayılan parametreler alabilir. Örnek: void greet([String name = 'Guest']) { print('Hello, \$name!'); } greet(); // Çıktı: Hello, Guest! greet('Fahri'); // Çıktı: Hello, Fahri! Anonim Fonksiyonlar Anonim fonksiyonlar, isimsiz fonksiyonlardır ve genellikle bir değişkene atanırlar. Örnek: var multiply = (int a, int b) { return a * b; }; print(multiply(3, 4)); // Çıktı: 12 Arrow Fonksiyonları Dart'ta kısa fonksiyonlar '=>' sembolü ile yazılabilir. Örnek: int square(int x) => x * x; print(square(4)); // Çıktı: 16 Yüksek Dereceli Fonksiyonlar Bir fonksiyon, başka bir fonksiyonu parametre olarak alabilir veya bir fonksiyonu döndürebilir. Örnek: void printResult(int Function(int, int) operation, int a, int b) { print(operation(a, b)); } printResult(add, 5, 3); // Çıktı: 8 Dr. Öğretim Üyesi Elyase İskender Yönetim Bilişim Sistemleri Mobil Programlama : Dart Programlama Dilinde En çok Kullanılan 50 Fonksiyon İçindekiler 3. print() 20. reversed() 37. skip() 4. main() 21. toUpperCase() 38. shuffle() 5. toString() 22. toLowerCase() 39. firstWhere() 6. isEmpty() 23. trim() 40. lastWhere() 7. isNotEmpty() 24. startsWith() 41. expand() 8. contains() 25. endsWith() 42. reversed() 9. length() 26. assert() 43. takeWhile() 10. substring() 27. Future.delayed() 44. skipWhile() 11. split() 28. await 45. indexWhere() 12. replaceAll() 29. Stream.listen() 46. lastIndexWhere() 13. add() 30. any() 47. singleWhere() 14. remove() 31. every() 48. toSet() 15. map() 32. fold() 49. toList() 16. forEach() 33. map() 50. toMap() 17. where() 34. removeWhere() 51. forEach() 18. reduce() 35. sort() 52. sort() 19. join() 36. take() print() Konsola veri yazdırmak için kullanılır. Örneğin loglama işlemi veya hata ayıklama amacıyla. void logMessage(String message) { print(message); } void main() { logMessage('Program started'); } main() Dart programlarının başlangıç noktasıdır. Programın akışını başlatmak için kullanılır. void main() { print('Application started'); } toString() Bir nesnenin string temsilini döner. Genellikle kullanıcıya gösterilecek veriyi hazırlamak için kullanılır. class Product { String name; double price; Product(this.name, this.price); @override String toString() { return 'Product: \$name, Price: \$price'; } } void main() { var product = Product('Laptop', 1200); print(product); } isEmpty() Bir koleksiyonun veya string’in boş olup olmadığını kontrol eder. List items = []; if (items.isEmpty) { print('The list is empty.'); } else { print('The list contains items.'); } isNotEmpty() Bir koleksiyonun veya string’in dolu olup olmadığını kontrol eder. List items = ['item1']; if (items.isNotEmpty) { print('The list has items.'); } else { print('The list is empty.'); } contains() Bir koleksiyon veya string’in belirli bir öğeyi içerip içermediğini kontrol eder. String text = 'Learn Dart programming'; if (text.contains('Dart')) { print('The text mentions Dart.'); } length() Bir koleksiyon veya string’in uzunluğunu döner. String text = 'Hello Dart'; print('The length of the text is: ${text.length}'); substring() Bir string’in belirli bir bölümünü döner. String text = 'Hello Dart'; String part = text.substring(0, 5); print(part); // Output: Hello split() Bir string’i belirli bir karaktere göre böler ve liste olarak döner. String sentence = 'Dart is amazing'; List words = sentence.split(' '); print(words); // Output: ['Dart', 'is', 'amazing'] replaceAll() Bir string içindeki belirli bir alt diziyi başka bir diziyle değiştirir. String text = 'Dart is fun'; String newText = text.replaceAll('fun', 'cool'); print(newText); // Output: Dart is cool add() Bir listeye yeni bir öğe ekler. List numbers = [1, 2, 3]; numbers.add(4); print(numbers); // Output: [1, 2, 3, 4] remove() Bir listeden belirtilen öğeyi çıkarır. List numbers = [1, 2, 3]; numbers.remove(2); print(numbers); // Output: [1, 3] map() Listedeki her öğeyi işleme tabi tutarak yeni bir liste oluşturur. List numbers = [1, 2, 3]; List squared = numbers.map((n) => n * n).toList(); print(squared); // Output: [1, 4, 9] forEach() Listedeki her öğeyi dolaşarak belirli bir işlem uygular. List numbers = [1, 2, 3]; numbers.forEach((n) => print(n * 2)); // Output: 2, 4, 6 where() Listedeki öğeleri filtreleyerek sadece şartı sağlayan öğeleri döner. List numbers = [1, 2, 3, 4, 5]; var evenNumbers = numbers.where((n) => n.isEven); print(evenNumbers); // Output: (2, 4) reduce() Listedeki tüm öğeleri işlemlerle tek bir değere indirir. List numbers = [1, 2, 3]; int sum = numbers.reduce((a, b) => a + b); print(sum); // Output: 6 join() Listedeki öğeleri birleştirerek bir string oluşturur. List words = ['Dart', 'is', 'awesome']; String sentence = words.join(' '); print(sentence); // Output: Dart is awesome reversed() Bir listeyi tersine çevirir. List numbers = [1, 2, 3]; var reversed = numbers.reversed; print(reversed); // Output: (3, 2, 1) toUpperCase() Bir string’i büyük harflere çevirir. String text = 'dart'; print(text.toUpperCase()); // Output: DART toLowerCase() Bir string’i küçük harflere çevirir. String text = 'DART'; print(text.toLowerCase()); // Output: dart trim() Bir string’in başındaki ve sonundaki boşlukları kaldırır. String text = ' Dart '; print(text.trim()); // Output: Dart startsWith() Bir string’in belirli bir karakterle başlayıp başlamadığını kontrol eder. String text = 'Dart programming'; print(text.startsWith('Dart')); // Output: true endsWith() Bir string’in belirli bir karakterle bitip bitmediğini kontrol eder. String text = 'Dart programming'; print(text.endsWith('ing')); // Output: true assert() Bir koşulun doğru olup olmadığını kontrol eder, yanlışsa hata fırlatır. int x = 5; assert(x > 0); // No error assert(x < 0); // Throws an error Future.delayed() Belirli bir süre sonra bir işlem gerçekleştirir. Future main() async { await Future.delayed(Duration(seconds: 2)); print('Executed after 2 seconds'); } await Asenkron işlemler gerçekleştirir, bir Future sonucunu bekler. Future fetchData() async { await Future.delayed(Duration(seconds: 1)); print('Data fetched'); } Stream.listen() Bir Stream’den veri alırken dinleyici ekler. Stream numbers = Stream.fromIterable([1, 2, 3]); numbers.listen((value) => print(value)); // Output: 1, 2, 3 any() Bir listedeki herhangi bir öğenin şartı sağlayıp sağlamadığını kontrol eder. List numbers = [1, 2, 3]; bool hasEven = numbers.any((n) => n.isEven); print(hasEven); // Output: true every() Bir listedeki tüm öğelerin şartı sağlayıp sağlamadığını kontrol eder. List numbers = [2, 4, 6]; bool allEven = numbers.every((n) => n.isEven); print(allEven); // Output: true fold() Bir başlangıç değeri kullanarak listeyi tek bir değere indirger. List numbers = [1, 2, 3]; int sum = numbers.fold(0, (prev, next) => prev + next); print(sum); // Output: 6 map() Bir listedeki her öğeye işlem uygulayarak yeni bir liste oluşturur. List numbers = [1, 2, 3]; List squared = numbers.map((n) => n * n).toList(); print(squared); // Output: [1, 4, 9] removeWhere() Belirli bir koşulu sağlayan öğeleri listeden çıkarır. List numbers = [1, 2, 3, 4]; numbers.removeWhere((n) => n.isEven); print(numbers); // Output: [1, 3] sort() Listedeki öğeleri sıralar. List numbers = [3, 1, 2]; numbers.sort(); print(numbers); // Output: [1, 2, 3] take() Listedeki ilk n öğeyi alır. List numbers = [1, 2, 3, 4, 5]; print(numbers.take(3)); // Output: (1, 2, 3) skip() Listedeki ilk n öğeyi atlar. List numbers = [1, 2, 3, 4, 5]; print(numbers.skip(3)); // Output: (4, 5) shuffle() Listedeki öğeleri rastgele sıralar. List numbers = [1, 2, 3, 4, 5]; numbers.shuffle(); print(numbers); // Example Output: [3, 1, 5, 4, 2] firstWhere() Şartı sağlayan ilk öğeyi bulur. List numbers = [1, 2, 3, 4]; int firstEven = numbers.firstWhere((n) => n.isEven); print(firstEven); // Output: 2 lastWhere() Şartı sağlayan son öğeyi bulur. List numbers = [1, 2, 3, 4]; int lastEven = numbers.lastWhere((n) => n.isEven); print(lastEven); // Output: 4 expand() Her listedeki öğeyi genişleterek yeni bir liste oluşturur. List matrix = [[1, 2], [3, 4]]; List flat = matrix.expand((i) => i).toList(); print(flat); // Output: [1, 2, 3, 4] reversed() Listeyi ters çevirir. List numbers = [1, 2, 3]; print(numbers.reversed); // Output: (3, 2, 1) takeWhile() Listedeki öğeleri, belirli bir şart sağlanana kadar alır. List numbers = [1, 2, 3, 4, 5]; var result = numbers.takeWhile((n) => n < 4); print(result); // Output: (1, 2, 3) skipWhile() Listedeki öğeleri, belirli bir şart sağlanana kadar atlar. List numbers = [1, 2, 3, 4, 5]; var result = numbers.skipWhile((n) => n < 4); print(result); // Output: (4, 5) indexWhere() Şartı sağlayan ilk öğenin indeksini döner. List numbers = [1, 2, 3, 4]; int index = numbers.indexWhere((n) => n.isEven); print(index); // Output: 1 lastIndexWhere() Şartı sağlayan son öğenin indeksini döner. List numbers = [1, 2, 3, 4]; int lastIndex = numbers.lastIndexWhere((n) => n.isEven); print(lastIndex); // Output: 3 singleWhere() Şartı sağlayan tek öğeyi döner, eğer birden fazla varsa hata verir. List numbers = [1, 2, 3]; int singleOdd = numbers.singleWhere((n) => n == 1); print(singleOdd); // Output: 1 toSet() Bir listeyi sete çevirir ve tekrar eden öğeleri kaldırır. List numbers = [1, 2, 2, 3]; Set uniqueNumbers = numbers.toSet(); print(uniqueNumbers); // Output: {1, 2, 3} toList() Bir iterable'ı listeye çevirir. Set numbers = {1, 2, 3}; List numberList = numbers.toList(); print(numberList); // Output: [1, 2, 3] toMap() Bir listeyi anahtar-değer çiftleri olarak bir haritaya (map) dönüştürür. List numbers = [1, 2, 3]; Map numberMap = numbers.asMap(); print(numberMap); // Output: {0: 1, 1: 2, 2: 3} forEach() Bir iterable üzerindeki her öğeye işlem uygular. List numbers = [1, 2, 3]; numbers.forEach((n) => print(n * 2)); // Output: 2, 4, 6 sort() Bir listedeki öğeleri sıralar. List numbers = [3, 1, 4, 1, 5]; numbers.sort(); print(numbers); // Output: [1, 1, 3, 4, 5] Mobil Programlama: Dart Dilinde Sınıflar Dr. Elyase İskender Yönetim Bilişim Sistemleri Bu bölüm, Dart dilinde Sınıflar konusuna giriş yaparak nesne yönelimli programlamanın (OOP) temel gereksinimlerini ele almaktadır. Bu bölümde sınıfların Sınıflar tanımlanması ve nesnelerin genişletilmesi gibi kavramları öğrenecek ve bu tekniklerin Dart becerilerinizi geliştirmede nasıl katkı sağladığını göreceksiniz. Dart’ta (ve genel olarak nesne yönelimli programlamada), class (sınıf), bir nesneye ait özelliklerin ve işlevlerin tanımlandığı bir Sınıfın Amacı yapıdır. Sınıflar, bir nesneye dair özellikleri (değişkenleri) ve davranışları (metotları) ve Faydaları: kapsar. Bu yapı, kodu daha düzenli, tekrar kullanılabilir ve yönetilebilir hale getirir. Sınıfın Amacı ve Faydaları: Nesne Tabanlı Yapı: Tekrar Kullanılabilirlik: Kapsülleme (Encapsulation): Sınıf, bir nesneye dair özellikler ve Bir sınıf, birçok nesne oluşturmak Sınıflar, veriyi ve fonksiyonları bir işlevler tanımlar. Bir sınıftan için şablon olarak kullanılabilir. Aynı arada tutarak kapsüllemeyi sağlar. oluşturulan her nesne, bu sınıfın bir sınıftan birçok nesne oluşturulabilir Verilere ve fonksiyonlara sınıf örneğidir (instance). ve bu nesneler aynı özellik ve dışından direkt erişimi sınırlayarak, Örneğin, Araba sınıfı, arabaların metotlara sahip olur. güvenliği ve veri bütünlüğünü korur. ortak özelliklerini (marka, model, Örneğin, Araba sınıfından birçok hız) ve davranışlarını (hızlanma, fren araba nesnesi (araba1, araba2 vb.) yapma) tanımlar. oluşturulabilir. Sınıfın Amacı ve Faydaları: Polimorfizm (Çok Modüler Yapı: Miras Alma (Inheritance): Biçimlilik): Sınıflar, kodu daha Sınıflar, miras yoluyla Aynı sınıfın farklı modüler ve okunabilir diğer sınıfların türevleri, kendi hale getirir. Bu, özelliklerini ve özellikleri ve karmaşık projelerde metodlarını kullanabilir davranışları ile farklı kodun yönetimini veya genişletebilir. Bu, şekillerde çalışabilir. kolaylaştırır. kodun tekrarını azaltır Polimorfizm, nesne Kod parça parça ve ilişkilendirilebilir tabanlı programlamada sınıflara bölünerek nesneler arasındaki aynı türdeki nesnelerin daha anlaşılır ve hiyerarşiyi destekler. farklı davranışlar sürdürülebilir bir yapı sergileyebilmesini elde edilir. sağlar. 1.Sınıf Temelleri: Bir sınıfın ne olduğunu, veri (özellikler) ve işlevselliği (yöntemler) bir araya getiren bir şablon olarak nasıl çalıştığını anlama. 2.Yapıcılar (Constructors): Nesneleri başlatmak ve sınıf özelliklerine başlangıç değerleri atamak için kullanılan özel yöntemleri öğrenme. Temel 3.Kalıtım ve Genişletme: Var olan sınıfları Konular: genişleterek alt sınıflar oluşturma, kodun tekrar kullanılabilirliğini sağlama ve hiyerarşi kurma. 4.Birden Fazla Sınıfın Kullanımı: Program içinde birden fazla sınıfın birlikte nasıl kullanılabileceğini öğrenerek modüler, düzenli ve sürdürülebilir kod yazma. Pratik Tavsiyeler: Basit Sınıflarla Başlama: İlk olarak basit sınıflar oluşturarak temel bilgilere odaklanın ve aşamalı olarak daha karmaşık yapılar ekleyin. Yetkinlik Kazanma: Sınıflar ile çalışmak başlangıçta zorlu olabilir, bu yüzden küçük adımlarla ilerlemek önemlidir. Konseptleri Uygulama: Gerçek dünya örneklerinde özel sınıflar oluşturarak öğrendiğiniz kavramları uygulayın; bu, daha karmaşık senaryoları yönetmenizi kolaylaştıracaktır. Örnek-1 Bu örnekte, bir Araç sınıfı tanımlayacağız, ardından bu sınıfı Araba gibi özel bir sınıfla genişleteceğiz. Örnek class Araba extends Arac { int kapiSayisi; // Üst sınıfın yapıcısını çağırıyoruz ve yeni özellik ekliyoruz // Temel bir Araç sınıfı tanımlıyoruz Araba(String marka, int yil, this.kapiSayisi) : super(marka, yil); class Arac { String marka; // Araba hakkında bilgi veren metod int yil; @override void bilgiVer() { super.bilgiVer(); // Üst sınıfın metodunu çağırıyoruz // Yapıcı (constructor) ile özellikleri başlatıyoruz print("Bu araba $kapiSayisi kapılı."); Arac(this.marka, this.yil); } } // Araç hakkında bilgi veren bir metod void bilgiVer() { void main() { print("Bu araç bir $yil model $marka."); // Arac sınıfından bir nesne oluşturuyoruz } var arac = Arac("Toyota", 2015); arac.bilgiVer(); // Çıktı: Bu araç bir 2015 model Toyota. } // Araba sınıfından bir nesne oluşturuyoruz // Araç sınıfından türetilmiş bir Araba sınıfı oluşturuyoruz var araba = Araba("Honda", 2020, 4); araba.bilgiVer(); // Çıktı: Bu araç bir 2020 model Honda. Bu araba 4 kapılı. } Açıklama: Arac Sınıfı: Araç için temel özellikler ve bir bilgi verme metodu içeren Arac sınıfı tanımlıyoruz. Bu sınıf, marka ve yil özelliklerini yapıcı (constructor) ile başlatıyor. Araba Sınıfı (Genişletilmiş Sınıf): Araba sınıfı, Arac sınıfından türetilmiştir. Araba sınıfı ayrıca kapiSayisi gibi ek bir özellik içermektedir. bilgiVer metodunu, super anahtar kelimesiyle üst sınıfın metodunu çağırarak genişlettik. main() Fonksiyonu: Hem Arac hem de Araba sınıflarından nesneler oluşturup bilgiVer metodunu kullanarak bilgileri ekrana yazdırıyoruz. Bu örnek, sınıf tanımlama, yapıcı kullanımı, sınıf genişletme ve metodları geçersiz kılma (override) gibi Dart’ın OOP özelliklerini açıklayıcı bir şekilde göstermektedir. Bu örnekte, haftanın kalan günlerini hesaplayan bir Dart sınıfı oluşturuyoruz. Bu sınıf, hem veri (değişkenler) hem de Örnek - 2 işlevsellik (metodlar) içeren bir yapı oluşturmayı gösteriyor. Aşamaları adım adım inceleyelim. const numDays = 7; Haftanın toplam gün sayısını temsil eden numDays sabitini tanımlıyoruz. class DaysLeftInWeek { int currentDay = Haftanın DateTime.now().weekday; Kalan Günleri int howManyDaysLeft() { return numDays - currentDay; } } Haftanın Kalan Günleri Özellikler: currentDay: Haftanın bugünkü gününü tam sayı olarak tutar (1 Pazartesi, 7 Pazar için) ve DateTime.now().weekday ile elde edilir. Metodlar: howManyDaysLeft(): Haftanın kalan gün sayısını, numDays değerinden currentDay değerini çıkararak hesaplayan bir fonksiyon. Haftanın Kalan Günleri void main() { var currentDay = DaysLeftInWeek(); print('Bugün haftanın ${currentDay.currentDay}. günü'); print('Hafta bitimine ${currentDay.howManyDaysLeft()} gün kaldı'); } Haftanın Kalan Günleri Bu örnek, aşağıdaki kavramları göstermektedir: Değişken ve Fonksiyonları Birleştirme: DaysLeftInWeek sınıfı, hem veri (currentDay) hem de mantığı (howManyDaysLeft) bir araya getiren bir kapsayıcıdır. Nesne Yönelimli Tasarım: Değişkenleri ve fonksiyonları bir sınıfta kapsayarak daha modüler ve düzenli bir yapı oluşturuyoruz; böylece kodu daha yeniden kullanılabilir ve sürdürülebilir hale getiriyoruz. Bu yaklaşımı kullanarak, hem değerleri hem de hesaplamaları tek bir nesne içinde yönetmenin esnek ve okunabilir bir yolunu oluşturuyoruz. Bu, kodun daha kolay yönetilmesini ve anlaşılmasını sağlar. Haftanın Kalan Günleri Dart, nesne yönelimli bir dil olup, tüm Dart nesneleri için (null hariç) temel olarak Object sınıfını kullanır. Bu, null olmayan bir nesnenin Object sınıfının bir alt sınıfı olduğu anlamına gelir. Örnekte, sınıf haftanın kalan günlerini belirlemek için kullanılmaktadır. class anahtar kelimesi, tanımı belirten bir yapıdır ve değişkenler ile fonksiyonları içerecek şekilde tanımlanır. Sınıfı kullanmak için, örneğin currentDay adlı bir değişken tanımlanarak sınıfın örneği oluşturulur. Bu değişken, sınıfla ilişkili hem değişkenlere hem de fonksiyonlara erişebilir. print ifadeleri, bir değişkene ve fonksiyona nasıl erişileceğini gösterir; bu sayede altındaki verilere ulaşılabilir. Bu örnek, Dart dilinde bir sınıfı genişletip yeni işlevsellik eklemenin nasıl Sınıfı yapılacağını gösteriyor. extends anahtar Genişletme kelimesi kullanılarak, mevcut bir sınıfa yeni özellikler ve metotlar eklemek için bir alt sınıf (subclass) oluşturulabilir. class Media { String title = ""; String type = ""; Media() { type = "Class"; } void setMediaTitle(String mediaTitle) { title = mediaTitle; Ana Sınıf: } String getMediaTitle() { Media return title; } String getMediaType() { return type; } } Media sınıfı, medya başlığı (title) ve türü (type) gibi temel özelliklere sahip. Yapıcı metot (Media), type özelliğini "Class" olarak ayarlar. setMediaTitle ve getMediaTitle metodları, başlık Açıklama bilgisini ayarlamak ve almak için kullanılır. getMediaType, medya türünü döndürür. class Book extends Media { String author = ""; String isbn = ""; AltSınıf Book() { type = "Subclass"; } void setBookTitle(String bookTitle) { title = bookTitle; } void setBookAuthor(String bookAuthor) { author = bookAuthor; } void setBookISBN(String bookISBN) { isbn = bookISBN; } String getBookTitle() { return title; } String getBookAuthor() { return author; } String getBookISBN() { return isbn; } } Açıklama Book sınıfı, Media sınıfından genişletilmiştir, yani Media author ve isbn gibi kitaplara sınıfındaki metotlara ve özgü özellikler eklenmiştir. özelliklere erişebilir. Kitap başlığı, yazarı ve ISBN Yapıcı metot (Book), type numarasını ayarlamak ve özelliğini "Subclass" olarak almak için çeşitli metodlar ayarlar. (setBookTitle, setBookAuthor, setBookISBN) kullanılır. Main Fonksiyonu void main() { var myMedia = Media(); Media sınıfından bir nesne (myMedia) myMedia.setMediaTitle('Tron'); oluşturulup başlık atanır ve türü ekrana print('Title: ${myMedia.getMediaTitle()}'); yazdırılır. print('Type: ${myMedia.getMediaType()}'); Book sınıfından bir nesne (myBook) var myBook = Book(); oluşturulup kitap başlığı ve yazar bilgileri atanır ve bu bilgiler ekrana yazdırılır. myBook.setBookTitle("Jungle Book"); myBook, Media sınıfının metotlarına ve myBook.setBookAuthor("R Kipling"); özelliklerine de erişebilir. print('Title: ${myBook.getMediaTitle()}'); print('Author: ${myBook.getBookAuthor()}'); print('Type: ${myBook.getMediaType()}'); } Bu örnek, bir sınıfı genişleterek ona özel ek özellikler ve işlevler kazandırmanın yararlarını göstermektedir. Örnekte: Media sınıfı genel bir yapı sağlarken, Book sınıfı bu yapı üzerinde daha spesifik bir bilgi ekler. Bu, bir sınıfın alt sınıfları aracılığıyla özelleştirilebileceği Tartışma anlamına gelir. extends kullanarak, Book sınıfı Media sınıfının özelliklerini ve metodlarını miras alır ve gerektiğinde kendi metodlarıyla veya ek özellikleriyle bu yapıyı genişletir. Bu yapıyı kullanmak, benzer veri yapıları arasında ufak farklılıklar olduğunda faydalıdır. Örneğin, Media genel medya bilgilerini içerirken, Book sınıfı kitaplarla ilgili özgün bilgilere sahiptir. Dart dilinde bir sınıfa, birden fazla sınıfın Sınıfları Mixin özelliklerini ekleyerek işlevsellik katmak için mixin kullanımını göstermektedir. ile Mixinler, bir sınıfın birden fazla sınıftan Genişletme işlev almasını sağlar ve özellikle çoklu kalıtım gereken durumlarda faydalıdır. Örnek abstract class SnickersOriginal { bool hasHazelnut = true; bool hasRice = false; SnickersOriginal ve SnickersCrisp soyut bool hasAlmond = false; (abstract) sınıfları olup, farklı çikolata } çeşitleri için temel özellikleri tanımlar. hasHazelnut, hasRice, ve hasAlmond gibi abstract class SnickersCrisp { bileşenlerin mevcut olup olmadığını belirtir. bool hasHazelnut = true; ChocolateBar sınıfı ise çikolata içeriğini bool hasRice = true; (hasChocolate) içerir. bool hasAlmond = false; } class ChocolateBar { bool hasChocolate = true; } class CandyBar extends ChocolateBar with SnickersOriginal { List ingredients = []; CandyBar() { if (hasChocolate) { ingredients.add('Chocolate'); Sınıfı } if (hasHazelnut) { Genişletme ingredients.add('Hazelnut'); } if (hasRice) { ingredients.add('Rice'); } if (hasAlmond) { ingredients.add('Almonds'); } } List getIngredients() { return ingredients; } } CandyBar Sınıfı: CandyBar sınıfı, ChocolateBar sınıfından türemiştir ve with anahtar kelimesi ile SnickersOriginal mixin'ini eklemiştir. Bu, CandyBar'a SnickersOriginal sınıfındaki özellikleri kazandırır. Açıklama CandyBar sınıfı ingredients listesini tutar ve yapıcı metot (constructor) ile bileşenlerin mevcut olup olmadığını kontrol ederek bu listeye ekler. getIngredients metodu, bileşen listesini döndürür. Main void main() { var snickersOriginal = CandyBar sınıfından bir snickersOriginal nesnesi Fonksiyonu CandyBar(); oluşturulur. getIngredients metodu ile print('Ingredients:'); bileşenler liste halinde alınır ve ekrana yazdırılır. snickersOriginal.getIngredi ents().forEach((ingredient) => print(ingredient) ); } Mixin Kullanımı: with anahtar kelimesi, CandyBar sınıfına SnickersOriginal sınıfındaki özellikleri kazandırır. Bu, çoklu sınıf özelliklerinin bir sınıfa eklenmesi gerektiğinde oldukça kullanışlıdır; çünkü CandyBar sınıfı, SnickersOriginal ve ChocolateBar sınıflarındaki özellikleri kullanabilir. İnceleme Soyut Sınıfların Tanımı: Çoklu İşlev Kazandırma: SnickersOriginal ve SnickersCrisp, temel Bu örnekte, CandyBar sınıfı birden fazla bileşenleri belirlemek için soyut sınıflar olarak sınıftan işlevsellik kazanmaktadır. tanımlanmıştır. Soyut sınıflar, bir sınıfa özellik SnickersOriginal mixin’i sayesinde, CandyBar kazandırırken örneği alınamaz, bu da mixin'ler sınıfı fındık veya pirinç gibi bileşenlere sahip için ideal bir kullanım sağlar. olup olmadığını kontrol edebilir ve bu bileşenleri listeye ekleyebilir. Mixin kullanımı, bir alt sınıfa ekstra işlevsellik kazandırırken, her seferinde yeniden kod yazma İnceleme ihtiyacını ortadan kaldırır ve çoklu işlevleri birleştirerek daha modüler bir yapı oluşturur. // Uçma yeteneğini temsil eden bir mixin oluşturuyoruz mixin Ucabilir { void uc() { print("Bu hayvan uçabiliyor."); } } // Yüzme yeteneğini temsil eden bir mixin oluşturuyoruz mixin Yuzebilir { Mixin ile Sınıf void yuz() { print("Bu hayvan yüzebiliyor."); Genişletmeye } bir başka } // Ana Hayvan sınıfı Örnek class Hayvan { String isim; Hayvan(this.isim); void tanit() { print("Ben bir $isim."); } } // Kus sınıfı, Hayvan sınıfını miras alır ve Ucabilir mixin'ini kullanır class Kus extends Hayvan with Ucabilir { Kus(String isim) : super(isim); } // Balik sınıfı, Hayvan sınıfını miras alır ve Yuzebilir mixin'ini kullanır class Balik extends Hayvan with Yuzebilir { Devam Balik(String isim) : super(isim); } // Ördek sınıfı, Hayvan sınıfını miras alır ve hem Ucabilir hem de Yuzebilir mixin'lerini kullanır class Ordek extends Hayvan with Ucabilir, Yuzebilir { Ordek(String isim) : super(isim); } Devam void main() { // Bir kuş nesnesi oluşturup özelliklerini yazdırıyoruz var kus = Kus("Serçe"); kus.tanit(); kus.uc(); // Çıktı: Bu hayvan uçabiliyor. // Bir balık nesnesi oluşturup özelliklerini yazdırıyoruz var balik = Balik("Somon"); balik.tanit(); balik.yuz(); // Çıktı: Bu hayvan yüzebiliyor. // Bir ördek nesnesi oluşturup özelliklerini yazdırıyoruz var ordek = Ordek("Yeşilbaş"); ordek.tanit(); ordek.uc(); // Çıktı: Bu hayvan uçabiliyor. ordek.yuz(); // Çıktı: Bu hayvan yüzebiliyor. } Açıklama Alt Sınıflar (Kus, Balik ve Mixin Tanımları: Ana Sınıf (Hayvan): Ordek): Ucabilir ve Yuzebilir adında iki mixin Hayvan sınıfı, tüm hayvanlar için ortak Kus sınıfı, Hayvan sınıfından miras alır tanımladık. Bu mixinler, uc ve yuz bir isim özelliğine sahiptir ve kendisini ve Ucabilir mixin'ini kullanarak uçma adında işlevler içerir. tanıtan tanit metodunu içerir. özelliği kazanır. Bu mixinler, özellikleri sınıflara esnek Balik sınıfı, Hayvan sınıfından miras bir şekilde eklememizi sağlar. alır ve Yuzebilir mixin'ini kullanarak yüzme özelliği kazanır. Ordek sınıfı, hem Ucabilir hem de Yuzebilir mixin'lerini kullanarak uçma ve yüzme özelliklerine sahip olur. Main Fonksiyonu: kus, balik, ve ordek adında üç nesne oluşturulur. Her nesne, kendi özelliklerine uygun olarak uc ve yuz metodlarını kullanır ve ekrana bu özellikler yazdırılır. Başka Örnek class Araba { // Metod: Araba hızını azaltır String marka; void fren(int azalma) { int hiz; hiz -= azalma; print("$marka yavaşladı, yeni hız: $hiz km/sa"); } // Yapıcı (constructor) } Araba(this.marka, this.hiz); void main() { // Metod: Araba hızını artırır var araba1 = Araba("Toyota", 60); void hizlan(int artis) { araba1.hizlan(20); // Çıktı: Toyota hızlandı, yeni hız: 80 km/sa hiz += artis; araba1.fren(30); // Çıktı: Toyota yavaşladı, yeni hız: 50 km/sa } print("$marka hızlandı, yeni hız: $hiz km/sa"); } Mobil Programlama FLUTTER’A GİRİŞ Flutter Frameworküne giriş Bu bölümde, Flutter Framework'e yolculuğumuza başlıyoruz ve Flutter'ın bazı temel kavramlarına odaklanıyoruz. Flutter ile başlarken temel kavramları ele almak önemlidir. Benim için bir Flutter uygulamasına başlamak için en iyi yer, uygulamanızın nasıl görüneceğini ve çalışacağını gösteren bir diyagramdır. Flutter ekibi, uygulamanızı kodlamaya başlamanız için geniş bir şablon yelpazesi sunarak sizin yanınızda. Başlangıç kodunu aldıktan sonra, uygulama tasarımlarınızı oluştururken sık sık karşılaşacağınız stateful ve stateless widget'lar arasındaki farkı anlamanın zamanı gelmiştir. Widget'ların yeniden düzenlenmesine (refactoring) kısa bir göz atıyoruz. Uygulamalarınıza karmaşıklık eklemek, bu işlemi defalarca tekrarlayacağınız anlamına gelir. Kodunuzu yeniden düzenlemek, hatalardan kaçınmak ve genel performansı artırmak için şiddetle tavsiye ettiğim bir beceridir. Neyse ki, Flutter’ın daha karmaşık arayüzler oluşturabilme yeteneği, bu zaman yatırımının gerçekten karşılığını verir. Arayüzleri Oluşturma Uygulamanızı tasarlamak için bir grafik paketi kullanın. Bütçenize ve kullanım durumunuza bağlı olarak, aşağıdaki seçenekler faydalı olabilir. Ürün Adı Bağlantı Fiyat Açıklama Genel bir web tabanlı Excalidraw https://excalidraw.com/ Ücretsiz grafik tasarım aracı. Uygulamalar için ortak bir Figma https://www.figma.com/ Ücretsiz/Ücretli tasarım ve geliştirme çözümü. Flutter kodunu oluşturan FlutterFlow https://flutterflow.io/ Ücretsiz/Abonelik etkileşimli UI şablonları ve bileşenler. Mocking an interface Bir arayüzü taklit etmek, Flutter gibi görsel bir framework ile başlamanın mükemmel bir yoludur. Ücretsiz çevrimiçi araçlardan, Flutter için özel olarak oluşturulmuş uygulamalara kadar birçok arayüz tasarım yöntemi vardır.Bir uygulamanın taklidini oluştururken, kullanılacak widget'lar perspektifinden arayüzü yakalamayı hedeflerim. Bunu yapmak, belirli tasarımları oluşturmayı kolaylaştırır. Daha karmaşık tasarımlarla uğraşıyorsanız, uygulamanın gereksinimlerini anlamak, daha temiz bir arayüz ve estetik tasarım sağlar. Arayüzleri Oluşturma Diyagramda, gerekli işlevselliği ve ekran geçişlerini dahil ediyorum. Arayüzü parçalara ayırmak, çeşitli widget'ların nasıl etkileşimde bulunduğunu öğrenmenin iyi bir yoludur. Ayrıca, widget'lar gibi doğru terimleri öğrenmek, uygun çözümleri bulmanıza yardımcı olur. Uygulama çok karmaşık olmasa da, Flutter kullanarak widget oluşturmanın temel ilkelerini öğrenmeme yardımcı oldu. Diyagramdan, bu tür bir arayüzün Flutter uygulamaları arasında oldukça yaygın olduğunu bilmelisiniz. Bir ListView eklemeyi öğrenmek ve aynı zamanda jestleri ve navigasyonu yönetmek esastır. Bu desenlerin her biri bu bölümde ele alınmıştır ve gelecekteki uygulamalar için bir referans görevi görebilir. Flutter Şablonları Tür Açıklama Bu, flutter create için varsayılandır Problem Yeni bir Flutter uygulaması app ve bir Flutter uygulaması oluşturmak istiyorsunuz ve bunu bir şablona oluşturmak için kullanılır. dayandırmak istiyorsunuz. Diğer uygulamalarla entegre Çözüm Uygulamanızı başlatmak için bir Flutter şablonu kullanın. Sıfırdan module edilebilecek bir modül başlamanıza gerek yok, çünkü Flutter çeşitli oluşturmanıza olanak tanır. uygulama şablonları sunmaktadır. Temel bir Paylaşılabilir bir Flutter projesi yapı sağlayan birçok farklı şablon mevcuttur. package oluşturmanıza olanak tanır. Flutter çerçevesinin daha yeni sürümlerinde, şablonlar şu türleri içerecek Android ve iOS ile kullanım için bir şekilde geliştirilmiştir: plugin API tabanı sağlar. Detay Görünümüne dayalı en iyi skeleton uygulama örneğini sunar. Flutter: Başlangıçtaki Komutlar Şablon komutunu, yani --template veya -t ekleyerek, Flutter'a oluşturma sırasında bir şablonun uygulanacağını belirtebilirsiniz. İşte şablonların nasıl kullanıldığına dair bazı örnekler İşlem Komut Varsayılan uygulama türünü oluşturmak flutter create my_awesome_app Bir modül oluşturmak flutter create -t module my_awesome_module Bir paket oluşturmak flutter create -t package my_awesome_package flutter create -t plugin my_awesome_plugin --platforms web --platform Bir eklenti oluşturmak android Bir iskelet uygulaması oluşturmak flutter create -t skeleton my_awesome_skeleton NOT: Bir eklenti oluştururken, desteklenecek platformu belirtmeniz gerekir. Eklenecek her platform için “ -- platform” önekini eklemeniz gerekmektedir. Flutter: Başlangıçtaki Komutlar Bir şablona dayalı bir proje oluşturduğunuzda, makinenizde mevcut olan cihazı dikkate almanız gerekir. Şablonlara ek olarak, API dokümantasyon web sitesindeki örnek kodlara da başvurabilirsiniz: http://docs.flutter.dev/. Site üzerindeki kodları kullanmak için, kullanılacak widget sayfasında bulunan örnek kimliğine referans vermeniz gerekir. Aşağıdaki örnekte, kodun bulunduğu web sayfası: https://api.flutter.dev/flutter/widgets/GestureDetector- class.xhtml. flutter create -s widgets.GestureDetector.1 my_awesome_sample Örnekler, çevrimiçi olarak mevcut içeriğe hızlı erişim sağlamak için kullanılabilir. Bir geliştirici olarak, hedef platforma ek olarak Web'i de hedeflemeyi amaçlamalısınız. Web'i dahil etmek mantıklıdır çünkü tarayıcıda uygulama testini etkinleştiren çok etkili bir yöntem sağlar. Geliştirme aşamasında, bu yaklaşım küçük ve büyük iyileştirmeler için geliştirici hızını önemli ölçüde artırabilir. Stateful Widget Stateful widget, Flutter'da durumunu (state) değiştirebilen ve yeniden çizim yapabilen widget'lardır. Yani, kullanıcı etkileşimleri, zamanla değişen veri veya herhangi bir dış etki sonucu durumunu güncelleyip arayüzde değişiklik gösterebilir. Örneğin: Bir sayaç uygulamasında, kullanıcı bir düğmeye her bastığında ekrandaki sayı artar. Bu tür bir uygulama, kullanıcı etkileşimi ile sürekli değişen bir durumu yönetmesi gerektiğinden, stateful bir widget kullanılarak yapılır. Stateful widget'lar, iki ana bileşenden oluşur: StatefulWidget sınıfı: Widget'ı tanımlar, ancak widget'ın durumunu yönetmez. State sınıfı: Widget'ın durumunu ve bu duruma bağlı olarak nasıl davranacağını yönetir. Bu sınıf, setState() fonksiyonu çağrıldığında widget'ı yeniden oluşturur ve UI'yi günceller. Stateful Widget ile Çalışmak Problem: Bir Flutter widget'ına bağlı bir durumu (örneğin, bir değeri) saklamak istiyorsunuz. Çözüm: Bir uygulama içinde bir değeri saklamak için Flutter StatefulWidget kullanın. Bir stateful widget'ın deklarasyonu, bir değerin saklanacağını gösterir. Aşağıdaki örnekte, durumu tutmak için bir widget tanımlanmıştır. import 'package:flutter/material.dart'; class MyTextWidget extends StatefulWidget { const MyTextWidget({Key? key}) : super(key: key); void main() { @override runApp(const MyApp()); _MyTextWidget createState() => _MyTextWidget(); } } class MyApp extends StatelessWidget { class _MyTextWidget extends State { const MyApp({Key? key}) : super(key: key); int count = 0; @override @override Widget build(BuildContext context) { Widget build(BuildContext context) { return GestureDetector( const title = 'Stateless Widget demo'; onTap: () { return MaterialApp( setState(() { title: title, count++; home: Scaffold( }); appBar: AppBar( }, title: const Text(title), child: Center(child: Text('Click Me: $count')), ), ); } body: const MyTextWidget(), } ), ); } } Açıklama Durum saklamak, değerin takip edilmesi gerektiğinden, bir Flutter uygulamasına karmaşıklık katar. Stateful widget kullanırken dikkate alınması gereken iyi bir desen, durum yönetimi ile ilişkili widget sayısını azaltmaktır. Flutter'da durum yönetimi genellikle Şekil 7-2'de gösterilen deseni kullanır. Bir stateful widget, bilgiyi saklamak için kullanılan birkaç yöntemin oluşturulmasını gerektirir. Açıklama MyTextWidget sınıfı, bir createState yöntemini uygulayan bir StatefulWidget'tır. Bu yöntemden döndürülen değer, _MyTextWidget adında özel bir değişkene atanır. Flutter'da, özel değişkenlerin önüne alt çizgi (_) karakteri eklenir. Özel değişkenin, daha önce gördüğümüz stateless widget'lara benzer şekilde nasıl yapılandırıldığına dikkat edin. Yeni bir setState fonksiyonunun tanıtılması, bir onTap olayı temel alınarak bir değerin saklanmasını sağlar. Örnekte, count değişkeni, her onTap olayı tetiklendiğinde artırılır. Özel _MyTextWidget sınıfı, durum değişikliğini başlatmak için kullanılır. Diyagramda, onTap() fonksiyonunun count değişkenini artırmak için kullanıldığı görülmektedir. Artık uygulamanın kullanıcısı etkileşime girip düğmeye bastığında, değişken artırılacak ve bu durum değişikliği uygulamada yansıtılacaktır. Stateful widget'lar ile çalışmak, stateless widget'lara göre daha fazla zorluk barındırır, ancak tasarımın dikkatlice ele alınmasıyla, aynı derecede etkili olabilir. Bir geliştirici olarak, minimum durum içeren bir uygulama tasarlayabilecek konumda olmalısınız. Bu, genel karmaşıklığı azaltır ve durum değişikliklerini güncellemek için yeniden çizimden kaynaklanan performans etkisini en aza indirir. Stateful widget'lar kullanırken göz önünde bulundurulması gereken bir diğer husus, bilgiyi nasıl ileteceğinizdir. Parametreleri iletmek için anahtarların nasıl kullanılacağına dair genel bir bakış için 11.5 numaralı tarife başvurabilirsiniz. Stateless widget Stateless widget, Flutter'da kullanıcı arayüzü oluşturmada kullanılan temel yapı taşlarından biridir. "Stateless" kelimesi, bu widget türünün bir durumu (state) olmadığını ifade eder. Bu, widget'ın kendisinin dinamik olarak değişen veri tutmadığı anlamına gelir. Yani, stateless widget bir kez oluşturulduktan sonra, yapılandırması sabit kalır ve sadece dış faktörler (örneğin, yeniden oluşturulma gibi) nedeniyle yeniden çizilir. Özellikleri: Sabit yapı: Stateless widget, kullanıcı etkileşimine bağlı olarak değişmeyen statik bir arayüz sağlar. Veri güncellemesi yok: Widget içerisinde veri güncelleme ya da yeniden yapılandırma yapma yeteneği yoktur. Performans: Durumu yönetme ihtiyacı olmadığından genellikle performans açısından daha verimlidir. Stateless Widget ile Çalışmak Problem Ekrandaki içerikle ilişkili bir durumu (yani bir değeri) kaydetmenize gerek yok. Çözüm Ekrandaki içeriği yalnızca görüntülemek için bir stateless widget kullanın. Aşağıdaki örnek nasıl yapıldığını gösteriyor. import 'package:flutter/material.dart'; class MyTextWidget extends StatelessWidget { const MyTextWidget({Key? key}) : super(key: key); void main() { runApp(const MyApp()); @override } Widget build(BuildContext context) { return const Center( class MyApp extends StatelessWidget { child: Text('Hello'), const MyApp({Key? key}) : super(key: key); ); } @override } Widget build(BuildContext context) { const title = 'Stateless Widget demo'; return MaterialApp( title: title, home: Scaffold( appBar: AppBar( title: const Text(title), ), body: const MyTextWidget(), ), ); } } Açıklama Örnekte, bir StatelessWidget kullanılarak bir Text widget'ı görüntülenmiştir. Stateless bir widget, değer saklamanın gerekli olmadığı anlamına gelir. Çoğu zaman, durumu saklamayı düşünmeniz gereken durumlarla karşılaşabilirsiniz. Kullanılacak widget'ların gereksinimlerini en iyi şekilde nasıl entegre edeceğinizi değerlendirin. Flutter, stateless ve stateful widget'lar arasındaki etkileşimde oldukça esnektir; bu yüzden sadece biri ya da diğeri arasında seçim yapmanız gerektiğini düşünmeyin. Bu örnekte, saklanacak bir değer yoktur. Ekranda bir değerin görüntülenmesi, bilgi saklamayı gerektirmediğinde bu tür bir widget kullanın. Durumsuz çalışmak, uygulamanızın nasıl çalıştığıyla ilgili olarak dikkate almanız gerekenlerin daha az olması nedeniyle en kolay seçenektir. Mümkünse, pratik olduğu durumlarda kod geliştirme sürecinin genel karmaşıklığını azaltmak için stateless bir tasarıma yönelmeye çalışın. Widget'ların Refaktörü Kodun okunabilirliğini ve sürdürülebilirliğini iyileştirmek için refaktörizasyon kullanımı Problem Kodun okunabilirliğini iyileştirmek için bir yol arıyorsunuz. Çözüm Kodun genel güvenilirliğini artırmak için refaktörizasyon kullanın. Refaktörizasyon, kodu basitleştirmenizi sağlar. Tartışma Okunabilirlik, kod kalitesinin ve sürdürülebilirliğinin önemli bir yönüdür. Basitçe, kodun anlamının ne kadar kolay anlaşılabildiğini ifade eder. Başlangıç kodunda: Gömülü Veri: Bağlantılı görüntü verisi ana kod tabanına sabitlenmiş, bu da değiştirmeyi zorlaştırır ve hata yapma olasılığını artırır. Widget Entegrasyonu: Container widget'ı doğrudan body içinde gömülü, bu da esnekliği azaltır ve gelecekteki iyileştirmeleri zorlaştırır. Refaktörizasyonun Faydaları 1. Kod İzolasyonu: Widget'ı kendi sınıfına taşımak, onu bağımsız ve yeniden kullanılabilir hale getirir. 2. Sorumlulukların Ayrılması: Ayrı bir ImageItem veri sınıfı oluşturmak daha iyi kod organizasyonu sağlar. 3. Geliştirilmiş Esneklik: Widget'ın bağımsız geliştirilmesi testleri basitleştirir. 4. Tutarlılık: Widget uygulama genelinde tutarlı şekilde çağrılabilir. Flutter Framework: Widgets Bu bölümde, Flutter Framework ile yolculuğumuza devam ediyoruz. Şimdi en yaygın widget'ların genel bir incelemesine geçiyoruz. Widget'lar, Flutter'da temel bir kavramdır ve çoğu uygulamanın temelini oluşturur. Mevcut birçok widget türünü nasıl entegre edeceğinizi öğrenmek, geliştirme becerilerinizi önemli ölçüde artıracaktır. Scaffold, Row ve Column Container gibi widget'ları ve diğerlerini nasıl kullanacağınızı anlamak, geniş bir yelpazede uygulamalar geliştirmenizi sağlayacaktır. Bu girişin bir parçası olarak, umarız widget'ları nasıl birleştireceğinizi ve zengin özelliklere sahip, güzel arayüzler oluşturacağınızı da fark edersiniz. Flutter uygulamalarının temel yapı taşlarının ötesinde nasıl inşa edileceğini bilmek, güveninizi yavaş yavaş artıracak ve daha karmaşık uygulamaların temelini oluşturacaktır. Scaffold Sınıfını Kullanma Problem Uygulamanızda material design düzeni ile çalışmak istiyorsunuz. Çözüm Uygulama içinde material bir arayüz sunmak için Scaffold kullanın. Örnekte, bir Scaffold düzeninin tipik öğelerini tanımlıyoruz. Scaffold Tartışma Scaffold kullanıldığında mevcut alanı doldurur ve ekran değişikliklerine göre dinamik olarak ayarlanır. Bu davranış, uygulamanızın genellikle ekranı doldurmasını isteyeceğiniz için arzu edilir. Ekran klavyesi mevcut olduğunda, varsayılan Scaffold ek bir mantık eklenmeden dinamik olarak ayarlanır. Scaffold, uygulamanızı AppBar (Bkz. Tarif 8.2) ve Drawer widget'ları ile geliştirme yeteneği sağlar (Tarif İlerleyen Bölümlerde). Scaffold'u FloatingActionButton ile kullanmak isterseniz, ilişkili buton durumunu korumak için Stateful bir widget kullanın. Kodunuza eklemek için Stateful widget (ilerleyen tariflerde) takip edilebilir. Genel olarak, Scaffold sınıfını iç içe kullanmaktan kaçının, çünkü Scaffold, bir MaterialApp için üst düzey bir konteyner olarak tasarlanmıştır. AppBar Kullanma Problem Uygulamanızın üst kısmında bir araç çubuğu başlık bölümü göstermek istiyorsunuz. Çözüm Uygulamanızın başlık bölümünü kontrol etmek için bir AppBar widget kullanın. İşte Flutter'da bir AppBar widget ile nasıl çalışılacağını gösteren bir örnek: AppBar Expanded Widget Kullanma Problem Ekranda mevcut olan alanı otomatik olarak kullanmak istiyorsunuz. Çözüm Expanded widget'ı, kullanıcıya görünen mevcut alanı (örneğin, görüntüleme alanını) düzenlemek için kullanın. Örnekte, ekranda mevcut boyutları kullanmak üzere üç öğeyi tanımlamak için Expanded widget'ı kullanıyoruz. Expanded Widget Tartışma Expanded widget'ın basitliğine rağmen, birçok kullanım durumunda faydalı olabilir. Örnekte, ekran boyutları üzerinde sorgu yapmak yerine Expanded widget'ı, mevcut alanı otomatik olarak doldurmak için kullanılmıştır. Adından da anlaşılacağı gibi Expanded, ekran boyutlarına otomatik olarak genişler. Oranları belirtmenize gerek yoktur, bu oranlar dinamik olarak hesaplanır. Expanded widget'ın davranışı, Listeler ile çalışırken özellikle yararlıdır. Yukarıdaki ListView widget'ını düşünün; bu widget, çalıştırma sırasında ListTile widget'ları ile dikey bir listeyi dinamik olarak doldurur. Tek başına kullanıldığında ListView, görüntüleme alanındaki mevcut boyutları tüketmeye çalışacaktır. Expanded Widget Burada Expanded widget, ListView'e, kalan görüntüleme alanını (yani kullanıcının ekranda görebildiği alanı) tüketmesi gerektiğini belirtmek için kullanılır. Ekranda başka widget'lar da kullanmayı tercih ederseniz, uygulamanız her öğe arasındaki görüntüleme alanı dağılımını nasıl oranlayacağını bilmek isteyecektir. Bu durumda, Expanded widget, görüntüleme alanında mevcut olan doğru boyutları otomatik olarak sağlamak için kullanılabilir. Mobil Programlama 6. Hafta: Stateless Widgetlara daha yakından bakalım Bir Widget Nedir ve Ekrana Nasıl Çizilir? Genel olarak, widget her şey olabilir; bir kutu, bir dolma kalem ya da bir ayakkabı bağcığı olabilir. Bu üç öğenin ortak noktası, hepsinin küçük, basit ve belirli bir amaca yönelik olmasıdır. Her biri tek bir şey yapar ve bunu iyi yapar. Flutter'daki widget'lar da küçük, basit ve belirli bir amaca yöneliktir. TextArea, Container ve Column gibi widget'larla karşılaşırsınız. Bu widget'ların her birinin tek bir görevi vardır: bir kullanıcıya metin girmesi için bir alan sağlamak, başka bir widget'ı barındırmak veya dikey bir widget yığını oluşturmak gibi. Flutter, agresif bir bileşim tasarım paradigması kullanır. Bu paradigmada, sadelik esastır. Bir widget'ı doğrudan stilize etmek (padding eklemek, pozisyonunu değiştirmek, döndürmek vb.) yerine, birden fazla widget'tan oluşan bir widget ağacı, tekil, belirli bir amaca yönelik widget'lardan inşa edilir. En karmaşık widget'lardan bazıları, örneğin Material widget, diğer widget'lar kullanılarak oluşturulur. (Material örneğinde, AnimatedDefaultTextStyle, NotificationListener ve AnimatedPhysicalModel kullanılır.) Bu yüzden widget'ları anlamak, Flutter'ı anlamak için hayati önem taşır. Widget'ları tam anlamak için, widget'ların ekrana nasıl render edildiğinden bahsetmemiz gerekir. Her widget'ın bir build() metodu vardır. Flutter bir widget'ı render etmek istediğinde, build() çağrılır, uygulamanın durumu değerlendirilir ve bir widget döndürülür. Döndürülen widget, çocukları olmayan basit bir widget olabileceği gibi, her birinin kendi build() metodu ve olası çocuk(ları) olan bir veya daha fazla çocuğa da sahip olabilir. Bu süreç sürekli olarak devam eder, her zaman uygulamanın mevcut durumunu değerlendirir ve gerektiğinde yeni widget'lar döndürür. Neredeyse her durumda, döndürülen widget(lar) diğer, daha ilkel widget'lardan oluşur. Bu widget'lar topluca bir widget ağacı oluşturur, ki Flutter bunu eleman ağacını ve nihayetinde render ağacını oluşturmak için kullanır. Element ve render ağaçlarını ilerleyen bölümlerde keşfedeceğiz, şimdilik aşağıdaki örnek üzerinden widget ağacına bakalım. Container( color: Colors.lightBlue, // Container'ın arka plan rengini açık mavi olarak ayarlar. child: Row( // Container'ın child öğesi olarak bir Row widget’ı tanımlanır. children: const [ // Row içinde iki çocuk widget sabit olarak belirtilir. Image( image: NetworkImage( 'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg' ), // İlk çocuk widget bir ağ üzerinden yüklenen bir görüntüdür. ), Text('Flutter is fun!'), // İkinci çocuk widget bir metin widget’ıdır. ], ), ) Bu kod, açık mavi renkte bir Container widget'ı oluşturacak ve içinde bir Row widget'ı barındıracak. Row içinde iki widget bulunur: bir Image widget'ı ve bir Text widget'ı. Uygulamamıza bu yapı eklendiğinde, ekranımızda şunları göreceğiz: Arka planı açık mavi olan bir alan. Sol tarafta bir baykuş resmi (Image widget). Sağ tarafta ise "Flutter is fun!" ifadesini içeren bir metin (Text widget). Bu basit örnek, Flutter’ın bileşen yapısı sayesinde farklı widget'ların bir araya gelerek nasıl daha karmaşık görüntüler oluşturabileceğini gösterir. Örnek Kodun Widget Ağacı Ancak pratikte, Flutter'ın oluşturduğu widget ağacı biraz daha karmaşıktır. Flutter uygulamalarınızı oluştururken ve hata ayıklarken, Flutter'ın düzen oluşturmak için kullandığı widget'lar her zaman hemen görünür olmayabilir. Dart DevTools'un bir bileşeni olan Flutter Inspector gibi araçlar sayesinde, render edilen herhangi bir widget'ı inceleyebilir, widget ağacına eklenen widget'ları görebilir ve widget ağacının kendisine bakabilirsiniz Container( width: 100, // Container genişliği 100 birim olarak ayarlandı. color: Colors.blue, // Container arka plan rengi mavi olarak ayarlandı. child: Row( // Container içinde bir Row widget tanımlandı. children: const [ Text( 'This text will overflow its constraints.', // Uzun bir metin içeren Text widget. softWrap: false, // Metin yumuşak sarma yapmaz, yani satır atlamadan devam eder. overflow: TextOverflow.visible, // Taşan metin görünür kalır. ), ], ), ) Row widget'ı, kısıtlarının ihlal edilmesine oldukça hassastır. Bir Row'u bir Container içine yerleştirerek, Row’un kısıtlarını sınırlayabiliriz. (Bunu yapmazsak, Row, tuvalin veya diğer ebeveyn widget'larından geçen tüm kısıtların boyutuna kadar genişler.) Row’u sınırladığımızda, tek bir çocuk öğe olarak bir Text widget'ı ekleriz ve bu widget'ın kısıtları aşması durumunda metnin sarılmamasını veya kırpılmamasını sağlamak için gerekli argümanları kullanırız. Uygulamada, bu tür bir yapı yaygın olarak kötü kod olarak kabul edilir. Ancak, bu yapı, bir widget'ın boyutunun kısıtlarını aştığında alacağınız hatayı mükemmel bir şekilde örneklemektedir. Kısıtları kullanarak, bir kullanıcı arayüzü (UI), mevcut ekran boyutuna göre şekil alabilir ve uyum sağlayabilir. Bu sayede UI, mobil ekran ile bilgisayar ekranı gibi farklı senaryolarda farklı düzenler sağlayarak responsive (duyarlı) bir tasarım kazanır. Stateless Widgets Stateless widgets, hem oluşturulma ve kullanım şekli hem de işlevselliği açısından üç tür widget arasında en basit olanıdır. Genellikle kullanıcı arayüzünü tanımlamak için kullanılırlar. En önemli özelliklerinden biri, mutable (değişken) bir duruma ihtiyaç duymamalarıdır. Ancak, StatelessWidget'ler, yapılandırıcı parametreler (constructor arguments) alabilir. Bir yapılandırıcı parametre, widget'a bir değişken (argüman) iletilmesini sağlar ve bu değişken, widget'ın özellikleri (properties) olarak görünüm, his, davranış veya diğer yönlerini özelleştirmek için build() metodu sırasında kullanılır. Bir stateless widget'ın build() metodu genellikle yalnızca widget ilk defa widget ağacına eklendiğinde, widget’ın ebeveyni değiştiğinde veya bağımlı bir kalıtılmış widget değiştiğinde çağrılır. StatelessWidget, kendi soyut sınıfıdır; yani, tüm bu sınıfa dayalı sınıfların temel davranışını tanımlamak için kullanılır, ancak kendisi başlatılamaz (örneklenemez). Şimdi, Material paketinin varsayılan parçası olan en yaygın stateless widget'lardan bazılarına ve kullanım durumlarına göz atalım; ardından, kendi widget'larımızı oluşturmaya geçeceğiz. Container Container widget, en yaygın kullanılan stateless widget'lardan biridir. Bir düzen (layout) widget’ı olarak kullanılır ve tek bir çocuk widget içerebilir. Container ilk başta sıkıcı bir widget gibi görünebilir, ancak ondan fazla kullanılabilir özelliği ile en çok yönlü widget'lardan biridir! Container widget’ı en iyi bir örnekle açıklanabilir. Örneğimizde, mevcut özelliklerin çoğunu (hepsini değil) kullanarak aşırı bir örnek oluşturacağız. Örnek Container’a (Şekil 4.5) göz atın. Bu örnek, Container’ın ne kadar güçlü ve özelleştirilebilir olduğunu göstermek için detaylı bir inceleme sunacaktır. Container( foregroundDecoration: BoxDecoration( // Container'ın üst width: 100, // Genişlik 100 birim olarak ayarlandı. katmanı için dekorasyon tanımlandı. height: 100, // Yükseklik 100 birim olarak ayarlandı. border: Border.all( // Kenarlık oluşturuldu. margin: const EdgeInsets.only( // Sadece üstten ve soldan kenar boşlukları eklendi. width: 5, // Kenarlık kalınlığı 5 birim. top: 20, color: Colors.grey, // Kenarlık rengi gri. left: 100, style: BorderStyle.solid, // Kenarlık stili dolu (solid). ), ), decoration: BoxDecoration( // Container’ın dekorasyon özellikleri tanımlandı. gradient: const RadialGradient( // Radyal bir gradyan shape: BoxShape.circle, // Container dairesel bir şekle uygulandı. sahip olacak. colors: [ color: Colors.grey, // Arka plan rengi gri olarak ayarlandı. Colors.white, // Gradyan beyaz renkle başlar. ), Colors.white, // Orta kısım yine beyaz. child: const FlutterLogo(), // İçine bir Flutter logosu eklendi. Colors.black, // Dış kenara doğru siyah renk alır. padding: const EdgeInsets.all(30.0), // İçerideki elemanlar ], için 30 birim padding verildi. ), ), ) Kodun İncelenmesi Bu örnek ile Container'da kullanılan bazı özellikler Bu kod, bir Container şunlardır: widget'ının özelliklerini 1.width ve height: Container’ın boyutlarını ayarlamak geniş çapta kullanarak için kullanılır. oldukça özelleştirilmiş bir 2.margin: Widget’ın etrafındaki boşlukları belirlemek için kullanılır. Burada üst ve sol kenarlara boşluk verilmiştir. örnek oluşturur. Container 3.decoration: Arka plan rengi ve şekli gibi dekoratif widget'ı, Flutter’ın en çok özellikleri tanımlar. Bu örnekte, BoxDecoration kullanılarak dairesel bir şekil ve açık gri bir yönlü widget'larından arka plan rengi atanmıştır. 4.padding: İçindeki widget'ların kenarlardan ne kadar biridir ve burada birçok uzak olacağını belirler. farklı özellik kullanılarak 5.foregroundDecoration: Üst katman dekorasyonu özelleştirilmiştir. Kodun sağlar. Burada bir kenarlık ve gradyan uygulanmıştır. Bu örnek, Flutter'ın Container widget’ını kullanarak nasıl açıklamalı hali aşağıdaki detaylı bir şekilde özelleştirilebileceğini göstermektedir. gibidir: Container veya diğer widget'lar için mevcut tüm özellikleri nerede bulabileceğinizi merak ediyor olabilirsiniz. Bunun birkaç yolu vardır: Visual Studio Code Üzerinde Hover Etme: Visual Studio Code içinde widget’ın üzerine geldiğinizde, mevcut özellikleri tanımlayan bir kutu açılır. Bu sayede hızlı bir şekilde widget'ın sahip olduğu özelliklere göz atabilirsiniz. Çevrimiçi Dokümantasyon: Flutter widget'ları ve özellikleri hakkında daha kapsamlı bilgiye çevrimiçi dokümantasyondan ulaşabilirsiniz. Bu dokümantasyona Flutter API dokümanları üzerinden ulaşabilirsiniz. Bu sayfada tüm widget'lar ve özelliklerinin bir listesi bulunmaktadır. Widget'ın Kaynak Kodunu İnceleme: Visual Studio Code’da bir widget’ın üzerine gelip Ctrl (Windows) veya ⌘ (Mac) tuşuna basılı tutarak tıklarsanız, doğrudan widget’ın kaynak koduna atlayabilirsiniz. Bu, widget’ın iç işleyişini görmek ve özelliklerinin nasıl tanımlandığını anlamak için faydalıdır.Bu yöntemler, Flutter’daki widget'ları daha derinlemesine incelemenize yardımcı olur. Column and Row Column ve Row widget'ları benzer şekilde çalışır; bir dizi widget alır ve onları sırasıyla görüntüler. Column çocuklarını dikey olarak sıralarken, Row yatay olarak sıralar. Column ve Row widget'ları, öğeleri bir araya getirmek için oldukça uygundur. Örneğin, bir simgeyi bir metin etiketinin yanına yerleştirmek için bir Row kullanabilirsiniz. İşte bu durumu gösteren bir örnek: Row( children: const [ Icon(Icons.account_circle), Text('My Account'), ], ) Row yerine Column kullanarak, Icon widget'ının Text widget'ının üstüne yerleşmesini sağlayabilirsiniz. mainAxisAlignment ve crossAxisAlignment özelliklerini kullanarak, çocuk widget'ların hizalamasını daha da ayarlayabilirsiniz. Aşağıdaki örnekte, mainAxisAlignment özelliği değiştirilmiştir, böylece elemanlar arasında eşit boşluk oluşur. Ek olarak, bu davranışı daha iyi göstermek için başka bir Text widget'ı eklenmiştir. Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, // Elemanlar arasında eşit boşluk bırakır. children: const [ Icon(Icons.account_circle), // Kullanıcı simgesi Text('My Account'), // İlk metin etiketi Text('Another widget'), // İkinci metin etiketi ], ) Column widget'ı varsayılan olarak çocuklarını yatay eksende (horizontally) ortalar. Bu davranışı değiştirmek için crossAxisAlignment özelliğini kullanabilirsiniz. Hem Column hem de Row, Flutter'da bir kullanıcı arayüzü oluştururken vazgeçilmez araçlardır. Text Text widget'ı, Flutter uygulamalarında metin göstermek için kullanılır ve önceki örneklerde birkaç kez görmüştük. Şimdi, Text widget'ını daha ayrıntılı inceleyelim. Metin göstermek, düşündüğümüzden daha karmaşık bir görevdir, çünkü yalnızca Latin alfabesi değil, birçok farklı yazı sistemi, yazı tipi (typeface) ve stil seçeneği bulunmaktadır. Ayrıca, metnin kısıtları aştığında ne olacağını da hesaba katmamız gerekir. Neyse ki, Flutter’ın Text widget'ı bu tür zorluklarla başa çıkmamıza olanak tanır. Basit Bir Metin Gösterimi Metni varsayılan stilde göstermek oldukça kolaydır. Sadece Text widget'ına bir metin dizisi (string) eklemek yeterlidir. Parametre adı belirtmeye bile gerek yoktur. Text('Flutter is Fun!') Flutter çerçevesi, varsayılan metin stilini DefaultTextStyle widget'ında tanımlar. Bu widget, oldukça anlamlı bir şekilde adlandırılmıştır ve uygulamanın Theme'si aracılığıyla diğer widget'lara varsayılan metin stilini sağlar. Eğer bu varsayılan stili değiştirmek istiyorsak, style parametresini kullanarak kendi TextStyle değerimizi belirtebiliriz. Bu durumda, sağladığımız özellikler DefaultTextStyle üzerinde öncelikli hale gelir ve varsayılan stili geçersiz kılar. Text( "Flutter is fun!", // Gösterilecek metin style: TextStyle( backgroundColor: Colors.grey, // Metnin arka plan rengini gri yapar fontFamily: 'Neonderthaw', // Yazı tipi (font family) fontSize: 36, // Yazı boyutu wordSpacing: 24, // Kelimeler arası boşluk ), ) Text Evet, Text widget'ı ile bu tür özelleştirmeleri yapmak oldukça basittir. Daha büyük, kalın yazı tipi, renkli kenarlık (border) ve metni ebeveyn konteynerde ortalamak gibi işlemleri gerçekleştirmek için TextStyle ve Paint sınıflarını kullanabilirsiniz. Ayrıca, cascade notation (..) kullanarak birden fazla özelliği kolayca uygulayabilirsiniz. import 'dart:ui' as ui; // Gerekli kütüphane..style = PaintingStyle.stroke // Çizgi (stroke) stilinde boyama..strokeWidth = 3 // Kenarlık kalınlığı..shader = ui.Gradient.linear( // Gradyan tanımı Text( const Offset(0, 20), // Gradyanın başlangıç noktası 'Fancy text', // Gösterilecek metin const Offset(300, 20), // Gradyanın bitiş noktası textAlign: TextAlign.center, // Metni [ // Gradyan renkleri yatay olarak ortalar Colors.blue, Colors.red, style: TextStyle( ], fontSize: 72, // Yazı boyutu ), fontWeight: FontWeight.bold, // ), Kalın yazı ) foreground: Paint() // Kenarlık boyama işlemi Cascade Notation Cascade notation (..) ile aynı nesne üzerinde birden fazla işlemi daha kısa ve okunabilir bir şekilde gerçekleştirebiliriz. İşte cascade notation olmadan ve cascade notation kullanılarak yazılmış iki örnek: Non Cascade Örnek Paint paint = Paint(); paint.style = PaintingStyle.stroke; paint.strokeWidth = 4; Bu yöntemde paint nesnesi üzerinde her özelliği ayrı bir paint.shader = ui.Gradient.linear( satırda tanımlamak zorundayız, bu da kodun daha uzun const Offset(0, 20), olmasına neden olur. const Offset(200, 20), [ Colors.purple, Colors.orange, ], ); Cascade Notation Paint paint = Paint()..style = PaintingStyle.stroke..strokeWidth = 4 Cascade notation kullanarak, aynı nesne üzerinde birden fazla..shader = ui.Gradient.linear( işlemi tek bir satırda toplayarak daha okunabilir bir hale getirebiliriz: const Offset(0, 20), const Offset(200, 20), [ Colors.purple, Colors.orange, ], ); Evet, belirli bir metin parçasına vurgu yapmak veya font stillerini bir cümlenin ortasında değiştirmek istiyorsak farklı bir stratejiye ihtiyacımız var. Flutter’da bunu Text.rich yapıcısını kullanarak yapabiliriz. Text.rich yapıcısı, bir TextSpan nesnesini argüman olarak alır. TextSpan sayesinde, metnin her bir kısmına özel stiller uygulayabiliriz. Örnek: Text.rich ve TextSpan Kullanımı Aşağıda, belirli bir kelimeye vurgu yaparak farklı bir stil uygulayan bir örnek kod yer alıyor: Text.rich( Text.rich: Bu yapılandırıcı, birden fazla stil içeren TextSpan( karmaşık metinler için kullanılır. text: 'Flutter is ', // Normal stil uygulanacak metin TextSpan: style: TextStyle(fontSize: 24), // Genel metin stili children: [ TextSpan( ( İlk TextSpan text: 'Flutter is '), genel stil (font boyutu 24) ile başlayan metin parçasını tanımlar. text: 'fun', // Vurgu yapılacak kelime children: Alt TextSpan öğeleri tanımlar. Bu öğeler, style: TextStyle( farklı stillerle belirli metin parçalarını özelleştirmek fontWeight: FontWeight.bold, // Kalın yazı için kullanılır. color: Colors.blue, // Mavi renk fontSize: 28, // Daha büyük yazı boyutu Vurgulu Metin: ), TextSpan içinde text: 'fun' olarak belirtilmiştir. ), style parametresi ile bu kelimeye kalın (bold), mavi TextSpan( renkte ve daha büyük bir yazı boyutu uygulanır. text: ' and easy to learn!', // Normal stil ile devam eden Normal Stil ile Devam: metin text: ' and easy to learn!' olarak belirtilen son parça, ), varsayılan stil ile devam eder. ], ), ) Evet, Text widget'ının kısıtları değiştiğinde, yani gösterilecek alan daraltıldığında, Flutter'ın metni nasıl işleyeceğini kontrol edebiliriz. Varsayılan olarak, Text widget'ı metni sığacak şekilde otomatik olarak bir alt satıra sarar. Ancak, bu davranışı değiştirmek için softWrap parametresini kullanabiliriz. Evet, metin sığmadığında bir alt satıra sarılmadığı için alan dışına taşarak kesilecektir. Bu durumda, metin kenarlara yaklaştıkça yavaşça kaybolmasını sağlamak için Text widget'ında overflow özelliğini kullanabiliriz. Flutter, metnin taşmasını yönetmek için çeşitli seçenekler sunar; örneğin, TextOverflow.fade ile metni kenarlarda kaybolacak şekilde ayarlayabiliriz. Evet, metnin belirli bir alana sığmadığında üç nokta (...) ile kısaltılması için overflow özelliğini TextOverflow.ellipsis olarak ayarlayabiliriz. Bu, metnin bir alt satıra sarmasını önler ve taşan kısmı yerine üç nokta gösterir, böylece kullanıcıya metnin kısaltılmış olduğunu belirtir. Center Evet, web geliştirmede bir öğeyi hem yatay hem de dikey olarak ortalamak için birçok yöntem kullanılabilir ve bu, çoğu zaman karmaşık bir işlem olabilir. Geçmişte, CSS ile bunu yapmak daha zor ve uzun kod satırları gerektirirken, günümüzde modern araçlarla daha basit hale geldi. Ancak Flutter’da, bu görev çok daha kolaydır; yalnızca Center widget'ını kullanmak yeterlidir. Center widget'ı, Flutter’da içine aldığı öğeyi hem yatay hem de dikey olarak ortalar. Bu, Flutter'ın esnek ve kullanımı kolay widget yapısının avantajlarından biridir. Center( child: Text("Flutter is fun!"), )