Menu
CoddyTech

Quiz: Ergebnisseite

Teil des Abschnitts Projekte der Flutter-Journey von Coddy. Lektion 16 von 36.

Wenn die letzte Frage beantwortet ist, sollte das Quiz auf einem eigenen Bildschirm mit deinem Ergebnis enden. Das ist ein zweites Widget, ResultsScreen, und Navigator.push führt dich dorthin.

Der Ergebnisbildschirm benötigt zwei Zahlen: die Punktzahl und die Anzahl der Fragen. Er erhält sie über seinen Konstruktor als benannte Parameter mit required:

class ResultsScreen extends StatelessWidget {
  const ResultsScreen({super.key, required this.score, required this.total});

  final int score;
  final int total;
  ...
}

Bei der letzten Frage lautet der Text auf der Schaltfläche „Ergebnisse ansehen“ statt „Weiter“. Dieselbe Methode _next übernimmt beides: Bei der letzten Frage öffnet sie den Ergebnisbildschirm und kehrt zurück, sodass der Index nie über das Ende der Liste hinausgeht.

if (_isLast) {
  Navigator.push(context, MaterialPageRoute(
    builder: (context) => ResultsScreen(score: _score, total: questions.length),
  ));
  return;
}
challenge icon

Aufgabe

Mittel

Beende das Quiz auf einem Ergebnisbildschirm:

  • Schreibe einen ResultsScreen mit einem Scaffold, einer AppBar mit dem Titel Results und in der Mitte mit 24 Pixel Innenabstand You scored 3 out of 5 (mit den tatsächlichen Zahlen) im headlineSmall des Themes.
  • Zeige nach jeder Antwort die Schaltfläche an: Bei der letzten Frage mit der Beschriftung See results und bei den übrigen mit Next.
  • Bei der letzten Frage öffnet _next den Ergebnisbildschirm.

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() {
    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),
              if (!_isLast)
                FilledButton(
                  onPressed: _next,
                  child: const Text('Next'),
                ),
            ],
          ],
        ),
      ),
    );
  }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Projekte

Übe selbstständig: Online-Flutter-Compiler