Quiz: Noch einmal spielen
Teil des Abschnitts Projekte der Flutter-Journey von Coddy. Lektion 17 von 36.
Ein Quiz, das den Leuten Spaß macht, wird zweimal gespielt. Füge dem Ergebnisbildschirm eine Schaltfläche „Erneut spielen“ hinzu, die dich zurück zu Frage 1 bringt und den Punktestand auf 0 setzt.
Die Schaltfläche selbst schließt nur den Ergebnisbildschirm: Navigator.pop(context). Neu zu starten ist Aufgabe des Quizbildschirms, da sich der Index und der Punktestand in dessen Zustand befinden.
Navigator.push gibt ein Future zurück, das abgeschlossen wird, wenn der geöffnete Bildschirm geschlossen wird. Mache _next async und verwende await für den Aufruf von push: Die nachfolgenden Zeilen werden ausgeführt, wenn du zurückkehrst – und das ist der richtige Zeitpunkt zum Zurücksetzen.
await Navigator.push(context, MaterialPageRoute(...));
setState(() {
_index = 0;
_picked = null;
_score = 0;
});Auch der Zurück-Pfeil auf dem Ergebnisbildschirm schließt ihn, sodass damit ebenfalls eine neue Runde beginnt. Zu einem Ergebnisbildschirm gibt es nichts, wohin man zurückkehren könnte – genau das willst du.
Aufgabe
MittelNoch einmal spielen:
- Füge unter der Punktzahl auf dem Ergebnisbildschirm nach einem Abstand von 32 Pixeln eine
FilledButton.iconmitIcons.replayund der BeschriftungPlay againhinzu, die den Bildschirm schließt - Mache
_nextzu einerasync-Funktion, verwendeawaitfür den Push-Aufruf und setze dann den Index, die Antwort und die Punktzahl innerhalb vonsetStateauf den Anfang zurück
Probier es selbst
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const QuizScreen(),
);
}
}
class Question {
const Question(this.text, this.answers, this.correct);
final String text;
final List<String> answers;
final int correct;
}
const List<Question> questions = [
Question('Which widget stacks its children from top to bottom?', ['Row', 'Column', 'Stack', 'Wrap'], 1),
Question('Which language do you write Flutter apps in?', ['Kotlin', 'Swift', 'Dart', 'JavaScript'], 2),
Question('What does setState do?', ['Rebuilds the widget', 'Saves the app', 'Closes the screen', 'Plays a sound'], 0),
Question('Which widget shows a list you can scroll?', ['Container', 'SizedBox', 'Padding', 'ListView'], 3),
Question('Which widget adds space around its child?', ['Padding', 'Center', 'Icon', 'Text'], 0),
];
class QuizScreen extends StatefulWidget {
const QuizScreen({super.key});
@override
State<QuizScreen> createState() => _QuizScreenState();
}
class _QuizScreenState extends State<QuizScreen> {
int _index = 0;
int? _picked;
int _score = 0;
Question get _question => questions[_index];
bool get _answered => _picked != null;
bool get _isLast => _index == questions.length - 1;
void _pick(int answer) {
if (_answered) return;
setState(() {
_picked = answer;
if (answer == _question.correct) {
_score++;
}
});
}
void _next() {
if (_isLast) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResultsScreen(score: _score, total: questions.length),
),
);
return;
}
setState(() {
_index++;
_picked = null;
});
}
Color? _colorFor(int answer) {
if (!_answered) return null;
if (answer == _question.correct) return Colors.green;
if (answer == _picked) return Colors.red;
return null;
}
@override
Widget build(BuildContext context) {
final question = _question;
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Quiz'),
actions: [
Padding(
padding: const EdgeInsets.only(right: 16),
child: Center(
child: Text('Score: $_score', style: textTheme.titleMedium),
),
),
],
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Question ${_index + 1} of ${questions.length}',
style: textTheme.labelLarge,
),
const SizedBox(height: 8),
LinearProgressIndicator(
value: (_index + 1) / questions.length,
minHeight: 8,
borderRadius: BorderRadius.circular(4),
),
const SizedBox(height: 24),
Text(question.text, style: textTheme.headlineSmall),
const SizedBox(height: 24),
for (int i = 0; i < question.answers.length; i++)
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: FilledButton.tonal(
style: FilledButton.styleFrom(
backgroundColor: _colorFor(i),
foregroundColor: _colorFor(i) == null ? null : Colors.white,
padding: const EdgeInsets.all(16),
),
onPressed: () => _pick(i),
child: Text(question.answers[i]),
),
),
if (_answered) ...[
const SizedBox(height: 12),
Text(
_picked == question.correct
? 'Correct!'
: 'The answer is ${question.answers[question.correct]}',
textAlign: TextAlign.center,
style: textTheme.titleMedium,
),
const SizedBox(height: 16),
FilledButton(
onPressed: _next,
child: Text(_isLast ? 'See results' : 'Next'),
),
],
],
),
),
);
}
}
class ResultsScreen extends StatelessWidget {
const ResultsScreen({super.key, required this.score, required this.total});
final int score;
final int total;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Results')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'You scored $score out of $total',
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
),
);
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Projekte
1Projekt: To-do-Liste
To-do-Liste: Die AufgabenlisteTo-do-Liste: Eine Aufgabe hinzufügen4Projekt: Gewohnheitstracker
Gewohnheitstracker: Deine GewohnheitenGewohnheitstracker: Die Woche2Projekt: Quiz
Quiz: Die FrageQuiz: Richtig oder falschÜbe selbstständig: Online-Flutter-Compiler