Flutter & Dart Fundamentals | Örnek Quiz Uygulaması #16

Gauloran

Global Moderatör
7 Tem 2013
8,129
620

FLUTTER & DART FUNDAMENTALS | ÖRNEK QUİZ UYGULAMASI #16


Merhaba, hoş geldiniz. Bu konular tabii ki birbirinden bağımsız olarak da incelenebilir ancak eğer ilginizi biraz çektiyse serinin diğer konularını inceleyebilirsiniz. Konu adını seo daha iyi işlesin diye daha ilgili bir şekilde değiştiriyorum artık serinin hangi konusu olduğuna # sonrası numaradan bakabilirsiniz.

0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #1
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #2
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #3
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #4
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #5
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #6
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #7
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #8
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #9
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #10
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #11
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #12
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #13
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #14
0'dan İleri Seviyeye Mobil Uygulama Geliştirme Eğitimi Veriyorum #15

Şimdi devam edelim. En son sizi bir tekrar paradoksuna sokmuştum. Mecburen oradan devam edeceğiz. Şimdi bir lifting the state up konseptine uygun bir şekilde güzel bir örnekle beraber kodların da içerdiği konular:
  • Daha fazla Widget ile çalışma

  • Widgetlara transparency ekleme

  • Stateful Widget

  • Fonksiyonlarla çalışma ve initState metodu

  • Flutter Stateful Widget Lifecycle üzerine birkaç kelam

  • Ternary expression kullanımı ve karşılaştırma operatörleri

  • If yapısını anlamak ve Listlerde kullanmak

  • Dummy data kullanımı ve model sınıf

  • Column'ı basitçe konfigüre etmek

  • Tekrar kullanılabilir özel buton widgetımızı oluşturma

  • List elemanlarına erişme

  • Listi Mapleme ve Spread operatörü kullanımı

  • Alignment, Margin ve Padding hakkında konuşalım

  • Pub.dev'den package kullanalım Google Fonts

  • Fonksiyonlarla widgetlar arasında data gezdirelim

  • Birkaç örnek if kullanımı

Başlayalım. Bir noktadan sonra kod incelemeye döneceğini baştan söylemeliyim. Seriden gelenlere öncelik olması açısından. Öncelikle buraya kadar geldiyseniz seriden gelenler için sizleri tebrik ederim. Direkt bu konuya seriden bağımsız olarak geldiyseniz de sorun değil çünkü burada çeşitli teknik konseptlerden bahsettiğim için direkt konunun ortasından da ilerleyebilirsiniz. Bir kısmını açıklamalı olarak vereceğim ancak serinin bu noktasına kadar gelenler için açıklama yapmayacağım sadece kodlu inceleme bırakacağım yerler de konunun ilerleyen kısımlarında olacak.

Daha fazla widget ile çalışmadan önce bir oluşturalım. Hatırlarsak main() fonksiyonunun otomatik olarak çalıştırıldığını ve runApp() metodunun da main() içerisinde çağrılması gerektiğinden bahsetmiştik. runApp() de Flutter'a ekranda hangi UI elementlerinin gösterileceğini söylüyordu. Widget tree de runApp() içerisine dolaylı yoldan verilirdi başlatılırdı.

RESİM-1

Kod:
import 'package: flutter/material.dart';

void main(){
    runApp(MaterialApp(home: Scaffold(body: )));
}
projemizde lib klasörü altında yeni bir başlangıç ekranı manasına gelecek start_screen.dart dosyasını oluşturalım. Burada custom widget oluşturmamız gerek. Öncelikle bir objenin blueprinti olarak biz sınıflardan bahsetmiştik. Yani class oluşturmalıyız en nihayetinde. Dart oop bir dil olduğu için bütün valuelar objectlerdir. Bunlar için de blueprint olarak classları kullanırız.

Kod:
import 'package: flutter/material.dart';

class StartScreen extends StatelessWidget {
StartScreen({super.key});
@override
Widget build(context){
  return const Text('Start screen');
}

StatelessWidget tan extend edilen bir StartScreen sınıfı oluşturduk. StatelessWidget bizden build metodunu override etmemizi isteyecek. contexti kafaya takmayın. StatelessWidget bunu eklememizi istiyor @Override annotationunu vermemiz gerekecek. Bu build metodunun içerisinde de return Text() derseniz mesela direkt ekranda gözükecek şeyi verecektir. Örneğin içerisine return const Text('Start screen'); yazın const'u niye verdik eğer telefonun hafızasında veya cihazın hafızası diyelim bu text widgetı tekrar kullanıldığında yine o oluşturulan hafızadan çekilir ve böylece optimizasyon gerçekleşmiş olur. Ek olarak constructor fonksiyon eklememiz lazım named argümanlı olmalı (bunlar ne ne oluyor diyenleri önceki konuya alabiliriz), super.key kullanımından da bahsetmiştim. Kodları burada yazıyorum direkt copy paste yapamadığım için parantezlerde ufak tefek hatalar olabilir ancak serinin burasına kadar geldiyseniz zaten bu tarz ufak tefek şeyleri çözebilmeniz gerekmekte. Kodum karmaşık gözüküyor diyenlere cevap olarak her parantezin sonuna , ekleyip düzenleme kısayolunu kullanırsanız sorun çözülür.

Kod:
//main dosyasında yapılacak işlemler

runApp(
    MaterialApp(
        home: Scaffold(
            body: Container(
               child: const StartScreen(),
                decoration: BoxDecoration(
                    gradient: LinearGradient(
                        colors: [
                           
                        ]
                    )
                )
            )
        )
    )
)

Şimdi asıl farklı widgetlarla çalışma kısmına geçelim. main.dartta Start Screen widgetını Container ile sarmalıyoruz. StartScreen'in constructırını const yapın onu const yaptığınızda artık StartScreen kullanılırken const constructora sahip olduğu için başına const ekleyebileceksiniz. Daha sonra Container'a decoration veriyoruz ve ona uygun olarak BoxDecoration ile birlikte gradient propertysiyle LinearGradient() vererek Container için ayarlamalar yapabiliriz örneğin colors argümanıyla ki bu argüman Color içeren list bekliyor onları veriyoruz. En azından iyi bir gradient oluşturmak için 2 tane renk verin Colors.deepPurple, Colors. bişey bişey şeklinde istediğiniz gibi. Bir de unutmayın ki genelde child propertysi sona atılır. Şimdi StartScreen deki Text widgetını Center widgetı ile sarmalayın. Bu ortalanmasını sağlayacak.

Bir de LinearGradient'e begin falan diyerek Alignment vermek mümkün end diyerek de Alignment verebilirsiniz başlangıç ve bitiş nerden nereye olsun şeklinde. Start Screen ekranında 3 tane temel şey görüntülemek istiyoruz şimdi alt alta olacak diyelim. Bunun için Column dediğinizi duyar gibiyim. children argumanı bekler o da Widgetlardan oluşan bir List bekler.


Kod:
Center(
    child: Column(
        children: [
       
        ]
    )
)

pubspec.yaml dosyasına gidelim ve assets: kısmını comment'dan çıkartalım bir resim eklemek istiyoruz projemize. Bu serinin önceki konularında çokça yapıldığı için devam. Bunu yapıp assets/images klasör yapısını projenizde oluşturun Image() widgetını artık kullanabiliriz ama lokal image olduğu için Image.asset constructor fonksiyonuyla daha rahat gösterim yapabiliyoruz 'assets/images/resimadi.uzantisi' diyerek kullanabiliriz Image widgetını. Daha önce yaptığımız için kodunu bile yazmıyorum.

ZyN8yk.png


ZyNki8.jpg

Eklediğinizde epey büyük olacaktır. Küçültmek için width argümanını kullanabilirsiniz şimdilik 300'e çekelim onu. Daha sonra Column'da mainAxisSize'a MainAxisSize.min verirsek şu anki çalışmamız için daha iyi olur. Image widgetının altına da bir Text widgeti ekleyin. Aralarına da 1 tane SizedBox() widgetı atın SizedBox'ı da boşluk vermek için kullandığımızı biliyorsunuz. height argümanına 80 verin. Şimdi resim ve text widgetı arasında güzel bir boşluk çekmiş olduk. Text widgetına style: TextStyle() diyerek dekorasyon işlemlerini yapabiliriz. TextStyle içerisinde color: Colors.white, şeklinde dilediğiniz rengi verin. fontSize olarak da 24 atayalım şimdilik. Bir de buton ekleyin Text widgetından sonra. Bunların hepsini Column içinde yapmalısınız.

Kullandığım resmi sağ taraftan görebilirsiniz. Oluşturduğunuz buton OutlinedButton olsun textine de Quize başla veya Start quiz diyebilirsiniz. Ona da style vermek için style: ButtonStyle bekliyor aslında ama daha kolay yapmanın yolu OutlinedButton sınıfının styleFrom metodunu kullanmak onun içerisinde bu buton ile ilgili çeşitli stil olaylarını halletmemiz daha rahat oluyor. Buton rengini beyaz yapın.

Hatta OutlinedButton'ın icon constructor fonksiyonunu kullanarak yani OutlinedButton.icon() şeklinde kullanabilirsiniz. Sizden bir icon: bekleyecek. Icon olarak aslında Widget da verebilirsiniz önceki kullanımdaki texti de label: olarak verebilirsiniz. Icon(Icons.fluttericonlari) oradan siz istediğinizi seçin Flutter'da built-in iconlar mevcut. arrow_right_alt iconunu kullanmanızı tavsiye edebilirim bu proje için. Başına const ekleyebilirsiniz.

Eklediğiniz resmin birazcık soyut hale getirmek tasarım açısından daha iyi olabilir. Image.asset widgetınızı Opacity ile sarmalayarak bu yapılabilir. opacity: bekler sizden buraya da 0.0 ile 1.0 arasında bir aralık bekler. 0.0 full transparent olur gittikçe azalır transparentı. 0.4 falan verebilirsiniz. 0.1 nerdeyse görünmez falan olmalı. Ancak daha iyi bir yaklaşım var Opacityi kullanmak yerine direkt olarak Image.asset'e color verip color'ın transparent ayarını yapmak daha mantıklı ama şu an işimize gelmiyor.

Projede lib klasörüne yeni bir dosya ekleyin quiz.dart diye ve questions_screen.dart diye bir dosya daha ekleyin. Mantık şu main.dart içinde yaptığınız onca kodlamayı yani projenin sonundan kod atmış olacağım ancak şu şekilde:


Kod:
void main() {
  runApp(const Quiz());
}

bu hale getireceksiniz. quiz.dart dosyasında da bir stateful widget yapısı var state kısmında döndürülen ise şu şekilde:

Kod:
 return MaterialApp(
      home: Scaffold(
        body: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [
                Colors.black,
                Colors.white,
              ],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
          ),
          child: screenWidget,
        ),

Böylece daha sade bir çalışmayla parçalara bölerek ilerlemiş oluyoruz.

class Quiz extends StatefulWidget{} yaptığınızda
stateful widget oluşturmanın temel noktasını yapmış oluyorsunuz Stateful 2 yapıyla çalışır biri state diğeri de class kısmı 2 yapı dediğim 2 class
Diğer class ise _QuizState olarak verilen State<Quiz> şeklinde State<> olarak hangi sınıfın state'i anlamında Quiz diye belirtmiş oluyoruz. Şimdi biraz karmaşık gelmiş olabilir ancak durum şu şekilde:


Kod:
class Quiz extends StatefulWidget {
  const Quiz({super.key});

  @override
  State<Quiz> createState() {
    return _QuizState();
  }
}

class _QuizState extends State<Quiz> {
....

createState'i kullanıyoruz onu da override etmemiz gerekiyor Quiz widgetına constructor fonksiyon da eklememiz gerekli super.key veriyoruz bunu defalarca kez yaptığımız için artık anlatmıyorum bile. Diğer questions_screen.dart dosyası da statefulwidget olacak.

Bu arada tabiki var activeScreen = const StartScreen() tarzında activeScreen içerisinde widget tutabiliyoruz. Çünkü eninde sonunda widgetlarda objectlerdir. Yani value olarak verilebilir.
Daha sonra void switchScreen(){} diye bir fonksiyon oluşturabilirsiniz State<Quiz> altında. Orada da setState kullanarak activeScreen değişkene QuestionsScreen() koyabilirsiniz. Yani aslında yapmak istediğimiz mantık şu aktif ekran değişkenimiz var birisi başlangıç ekranını tutuyor ilk başta daha sonra bir metod oluşturduk bu metod da setState yapıyor yani build metodunu tetikleyecek ilgili yerleri güncellemek için ve bu oluşturduğumuz aktif ekran değişkenine başka bir ekran atayacak. Böylece bunu da bir butona bağladığımızda butona tıkladığımızda başka bir ekran göreceğiz. Aslında işin özeti bu.


ZyNoz1.png


ZyN1ao.png


Aşağıdaki kodu inceleyin. add metodu listlerde hangi liste add fonksiyonunu kullanıyorsan hafızadan ona erişir ve var olan listeye item ekler
yani final olarak tanımlanmış bir list bile olsa sıkıntı olmaz çünkü reassign yapmıyor item ekliyor hafızada var olana erişip
sıkıntı yok yani. Şimdi artık incelemelere başlayalım sizlerden kodları incelemenizi ve konunun en üst kısmında verdiğim başlıklarla ne nereyi anlatıyor diye eşleştirmenizi istiyorum.


Kod:
import 'package:flutter/material.dart';
import 'package:flutter_application_2/data/questions.dart';
import 'package:flutter_application_2/questions_screen.dart';
import 'package:flutter_application_2/start_screen.dart';

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

  @override
  State<Quiz> createState() {
    return _QuizState();
  }
}

class _QuizState extends State<Quiz> {
  List<String> selectedAnswers = [];

  String activeScreen = 'start-screen';

  void chooseAnswer(String answer) {
   
    selectedAnswers.add(answer);
    if (selectedAnswers.length == questions.length) {
      setState(() {
        selectedAnswers = [];
        activeScreen = 'start-screen';
      });
    }
  }

  void switchScreen() {
    setState(() {
      activeScreen = 'questions-screen';
    });
  }

  @override
  Widget build(context) {
    Widget screenWidget = StartScreen(switchScreen);

    if (activeScreen == 'questions-screen') {
      //if condition yapısı
      screenWidget = QuestionsScreen(
        onSelectAnswer: chooseAnswer,
      );
    }

    /*
    final screenWidget = activeScreen == 'start-screen' ? StartScreen(switchScreen) : const QuestionsScreen();
    /*
          ternary kullanımı blabla ? asdf : csdf
          blabla true ise asdf değilse csdf çalışır
          ufak ve işlevsel bir condition
           */
    böyle yapıp daha sonra childa screenWidget denilerek de kullanılabilirdi
     */

    return MaterialApp(
      home: Scaffold(
        body: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [
                Colors.black,
                Colors.white,
              ],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
          ),
          child: screenWidget,
        ),
      ),
    );
  }
}

Attığım kod içerisinde ternary expression anlatımı var çok ufak bir yere koydum. son haline yakın bir yerden atılmış ancak yine de inceleyin. Daha açıklayıcı olması açısından

start_screen.dart kodları:

Kod:
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

class StartScreen extends StatelessWidget {
  const StartScreen(this.startQuiz, {super.key});

  final void Function() startQuiz;

  @override
  Widget build(context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Image.asset(
            'assets/images/drawing_image.png',
            width: 300,
          ),
          const SizedBox(
            height: 80,
          ),
          Text(
            'Learn Flutter the fun way!',
            style: GoogleFonts.lato(
              color: Colors.white,
              fontSize: 24,
            ),
          ),
          const SizedBox(
            height: 30,
          ),
          OutlinedButton.icon(
            onPressed: startQuiz,
            style: OutlinedButton.styleFrom(
              foregroundColor: Colors.white,
            ),
            icon: const Icon(Icons.arrow_right_alt),
            label: const Text('Start Quiz'),
          ),
        ],
      ),
    );
  }
}

StartScreen de yapılan mantığı anlamak önemli. switchScreen fonksiyonuyla setState edilerek activeScreen değiştiriliyor. Questions_screen.dart'ı inceleyelim:

map fonksiyonu önemli listlerin map fonksiyonu var listenin her bir itemini alır ve o itemler için
bir kod satırı çalıştırabiliriz tek tek her biri için.
map fonksiyonu bir listenin içindekileri başka bir şeye dönüştürmeye yarayabilir
dart otomatik olarak tek tek listenin elemanlarını alıp fonksiyonu çalıştıracak
gerçek objeyi değiştirmez map yeni bir list oluşturur hafızada yani map değiştirmiyor orijinal listeyi.


! ... operatörü bir listedeki veya yinelenebilir olan(iterable) şeydeki değerlerin hepsini alır listeden çıkartır

flutterda state classlarda built in bir özellik var widget. diyerek asıl sınıftaki şeyleri kullanabiliyoruz erişebiliyoruz bu arada.

örnek:

Kod:
const numbers = [1,2,3];[/FONT][/CENTER][/FONT][/CENTER]
[FONT=verdana][CENTER][FONT=verdana][CENTER]            const moreNums = [numbers, 4]; ----> [[1,2,3],4];
            const moreNums = [...numbers,4]; --> [1,2,3,4];



shuffle metodu da var listlerin. ancak orijinal listeyi editliyor shuffle metodu.
baya hafızadaki şeyi editliyor yani.


Kod:
import 'package:flutter/material.dart';
import 'package:flutter_application_2/answer_button.dart';
import 'package:flutter_application_2/data/questions.dart';
import 'package:flutter_application_2/models/quiz_question.dart';
import 'package:google_fonts/google_fonts.dart';

class QuestionsScreen extends StatefulWidget {
  const QuestionsScreen({super.key, required this.onSelectAnswer});

  final void Function(String answer) onSelectAnswer;

  @override
  State<QuestionsScreen> createState() {
    return _QuestionsScreenState();
  }
}

class _QuestionsScreenState extends State<QuestionsScreen> {
  var currentQuestionIndex = 0;

  void answerQuestion(String selectedAnswer) {
    widget.onSelectAnswer(selectedAnswer); //bu aslında chooseAnswer fonksiyonunu kullanıyor yani quiz.dart dosyasındaki
    setState(() {
      currentQuestionIndex++;
    });
  }

  @override
  Widget build(context) {
    final QuizQuestion currentQuestion = questions[currentQuestionIndex];

    return SizedBox(
      width: double.infinity, //use as much width as you can demektir
      child: Container(
        margin: const EdgeInsets.all(
            40), //containerın margin verme özelliği vardır columnı container ile sarmalayıp margin verdik
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              currentQuestion.text,
              textAlign: TextAlign.center, //texti hizalamaya yarar yatayda
              style: GoogleFonts.lato(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 24,
              ),
            ),
            const SizedBox(
              height: 30,
            ),
          
            ...currentQuestion.getShuffledAnswers().map((answer) {
              return AnswerButton(
                answerText: answer,
                onTap: () {
                  answerQuestion(answer);
                },
              );
            }),
          ],
        ),
      ),
    );
  }
}

/*

*/

ZyNsyh.png


Flutter tarafından (belirli zaman noktalarında) otomatik olarak yürütülen bir yöntemlere Life cycle yöntemleri diyebiliriz. Bilmeniz gereken son derece önemli üç tanesini aşağıya açıklamasını bırakıyorum.

initState(): StatefulWidget'ın State nesnesi başlatıldığında Flutter tarafından yürütülür

build(): Widget ilk kez oluşturulduğunda ve setState() çağrıldıktan sonra Flutter tarafından yürütülür

dispose(): Widget silinmeden hemen önce Flutter tarafından yürütülür


Şimdi if statementlerı ve operatörler için zamanında aldığım yarı İngilizce yarı Türkçe bir notumu ki bu not bahsettiğimiz proje ile ilgili, buraya bırakayım gerekirse translate'e atıp inceleyebilirsiniz.

Kod:
if Statements & Comparison Operators

The if statement is a crucial feature of the Dart language - actually, it's a core feature of pretty much all programming languages.

In addition to what you learned in the previous lecture, in Dart, you may also use if inside of lists to conditionally add items to lists:

final myList = [
  1,
  2,
  if (condition)
    3
];

In this example, the number 3 will only be added to myList if condition was met

final myList = [
  1,
  2,
  if (condition)
    3
  else
    4
];


Using this feature is optional. Alternatively, you could, for example, also work with a ternary expression:

final myList = [
  1,
  2,
  condition ? 3 : 4
];


Especially when inserting more complex values (e.g., a widget with multiple parameters being set) into a more complex list (e.g., a list of widgets passed to a Column() or Row()), this feature can lead to more readable code.

Examples:

if (true) {
  // do something ...
}
// or
true ? 'this' : 'that'



veya


if (randomNumber == 5) {
  // do something
}

karıştırma

var userName = 'Max'; // assignment operator used
if (userName == 'Max') { ... } // comparison operator used

!= to check for inequality (randomNumber != 5 expects randomNumber to NOT be 5, i.e., to be any other value)

> to check for the value on the left to be greater than the value on the right (randomNumber > 5 yields true if randomNumber is greater than 5)

>= to check for the value on the left to be greater than or equal to the value on the right (randomNumber >= 5 yields true if randomNumber is greater than 5 or equals 5)

< to check for the value on the left to be smaller than the value on the right (randomNumber < 5 yields true if randomNumber is smaller than 5)

<= to check for the value on the left to be smaller than or equal to the value on the right (randomNumber <= 5 yields true if randomNumber is smaller than 5 or equals 5)

!PUB.DEV

pub.dev dart package larının toplandığı bir yer bir sürü package var kullanılabilecek.

Model sınıf ve dummy data ile ilgili söyleyeceklerim kod satırının içerisinde // olarak ekledim:

Kod:
//bu blueprint olacak sorular için model sınıf

class QuizQuestion {
  const QuizQuestion(this.text, this.answers);
  //bu constructor functionumuzda böyle

  final String text;
  final List<String> answers;

  List<String> getShuffledAnswers() {
    final shuffledList = List.of(answers);
    //Listlerin of constructor fonksiyonu var mesela yeni bir liste yapıyor başka bir listeyi base alarak.
    shuffledList.shuffle(); //shufle metodu listeyi harmanlar ve hafızada da değiştirir.
    /*
    burada final olarak tanımlanan List nasıl değişiyor?
    çünkü final olarak tanımlama yaptığımızda reassign yapamıyoruz artık. o yüzden değişmez diyoruz genel olarak.
    yani reassign yapılamaz shuffledList e yeni bir liste assign edemezsin. ama varolan list in içeriğini değiştirebilirsin.
   
     */
    return shuffledList;
  }
}

ve yine questions.dart içerisini de bırakıyorum ki bunu data klasörünün altında lib içerisinde koymanız gerekli.

Kod:
//dummy sınıf verileri tutacak QuizQuestion sınıfımızı oluşturmuştuk o model sınıftan burada nesneler oluşturacağız

import 'package:flutter_application_2/models/quiz_question.dart';

const questions = [
  QuizQuestion(
    'What are the main building blocks of Flutter UIs?',
    [
      'Widgets', //burada hep ilk cevap dogru olsun diye ayarlayacagiz ama UI da harman olarak gösteririz onu sıkıntı yok
      'Components',
      'Blocks',
      'Functions',
    ],
  ),
  QuizQuestion('How are Flutter UIs built?', [
    'By combining widgets in code',
    'By combining widgets in a visual editor',
    'By defining widgets in config files',
    'By using XCode for iOS and Android Studio for Android',
  ]),
  QuizQuestion(
    'What\'s the purpose of a StatefulWidget?',
    [
      'Update UI as data changes',
      'Update data as UI changes',
      'Ignore data changes',
      'Render UI that does not depend on data',
    ],
  ),
  QuizQuestion(
    'Which widget should you try to use more often: StatelessWidget or StatefulWidget?',
    [
      'StatelessWidget',
      'StatefulWidget',
      'Both are equally good',
      'None of the above',
    ],
  ),
  QuizQuestion(
    'What happens if you change data in a StatelessWidget?',
    [
      'The UI is not updated',
      'The UI is updated',
      'The closest StatefulWidget is updated',
      'Any nested StatefulWidgets are updated',
    ],
  ),
  QuizQuestion(
    'How should you update data inside of StatefulWidgets?',
    [
      'By calling setState()',
      'By calling updateData()',
      'By calling updateUI()',
      'By calling updateState()',
    ],
  ),
];

answer_button.dart'ı da veriyorum vermediğim kod dosyası kaldıysa yorumlardan belirtebilirsiniz.

Kod:
import 'package:flutter/material.dart';

class AnswerButton extends StatelessWidget {
  //ozel buton widgetı olusturuyoruz string isteyecek ullanırken bunu buton ismi olarak göstereceğiz bir de onpressed olarak ayarlayalım onu da istesin butonun ne yapacagını da soylesin kullanırken
  const AnswerButton({
    super.key,
    required this.answerText,
    required this.onTap,
  }); //constructor functionımız
  //ayarlarken required named parameter kullanacagız

  final String answerText;
  final void Function() onTap;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onTap,
      style: ElevatedButton.styleFrom(
        padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 40),
        foregroundColor: Colors.black,
        backgroundColor: Colors.yellow,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(40),
        ),
      ),
      child: Text(
        answerText,
        textAlign: TextAlign.center,
      ),
    );
  }
}

Böylece lifting state up konseptini ve soruların butonları art arda kullanmak yerine mapleyerek ve ... operatörünü kullanarak üstüne bir de shuffle metodunu da kullanarak güzel bir örnek yapmış olduk. Baştan sona yapmanız veya yapmamanız mühim değil zaten 16.konuya kadar seride geldiyseniz şu noktadan sonra bu gibi basit projelerin kodlarına göz gezdirip geçmenizi bekliyorum.

ZyNOzq.png
ZyNxV3.png
ZyNtKQ.png
 
Son düzenleme:

WHITERUBY

Uzman üye
20 Şub 2023
1,661
1,517
🔱
Elinize sağlık, diğer giriş seviye programa konuları gibi "Python Dersleri #1" gibi bir durum değil. Gayet uğraşılmış ve derin algoritma bilgisi içeren bir seri olmuş. Her ne kadar mobil programlamaya ilgim olmasa da... Tekrardan elinize sağlık. Masterpiece💯
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.