4.3 Aussagen und Antworten hinzufügen (inkl. Theorie zu Verzweigungen)
Jetzt wollen wir eine Liste von Aussagen erstellen und jedes Mal, wenn wir den Wahr oder Falsch Knopf drücken, sollte die App unsere Antwort überprüfen und zur nächsten Aussage in der Liste weiter gehen. Wenn Sie nach Wahr oder Falsch Aussagen googeln, werden Sie eine Vielzahl an Aussagen für Ihre Quiz-App finden.
Wir liefern Ihnen hier mal drei Smartphone-Mythen mit den richtigen Antworten (Quelle: https://www.20min.ch/story/6-handy-mythen-im-fakten-check-320589291508).
- 'Geöffnete Apps brauchen viel Akku.' Falsch – Nur Apps, die im Hintergrund Ortungsdienste verwenden oder multimediale Inhalte streamen brauchen im Hintergrund Akku und sollten bei Nicht-Nutzung geschlossen werden.
- ‘Eine Kamera mit mehr Megapixeln resultiert in besseren Bildern.' Falsch – Kameras mit mehr Megapixeln machen zwar Fotos in höherer Auflösung, das Objektiv und Sensoren entscheiden aber über die Qualität des Bildes.
- '5G frisst nicht mehr Daten als 4G.' Wahr – 5G ist zwar schneller als 4G, das bedeutet aber nicht, dass es mehr Daten frisst. Da die Daten schneller geladen werden, weckt es aber diesen Anschein.
Übung
Liste mit Aussagen erstellen
- Fügen Sie nach der scoreKeeper-Liste eine neue Liste mit dem Namen statements vom Datentyp String ein.
- Integrieren Sie in diese Liste die drei Smartphone-Mythen von oben ein.
- Ersetzen Sie den Platzhalter 'Hier erscheinen die Aussagen.' mit dem ersten Element aus der statements-Liste. (Hinweis: Auf das erste Listenelement können Sie entweder über statements[0] oder statements.first zugreifen.)
Nach der letzten Übung sollte die Quiz-App die erste Aussage auf dem Bildschirm darstellen.
Nachdem Sie es geschafft haben, die erste Aussage im Text-Widget anzuzeigen, müssen Sie als Nächstes eine Art Tracker resp. Zählvariable erstellen, um zu verfolgen, wo Sie sich in der Liste mit den Aussagen befinden. Im Moment befinden Sie sich bei 0 (also dem ersten Listenelement). Dieser Tracker hilft Ihnen zur nächsten Aussage zu gelangen sobald Sie auf die Schaltfläche Wahr oder Falsch tippen.
Übung
Zählvariable erstellen
- Fügen Sie direkt nach der statements-Liste eine Zählvariable von dem Datentyp int ein und initialisieren Sie diesen Wert mit 0.
- Ändern Sie anschliessend im Text-Widget, wo der Code statements[0] oder statements.first steht, den Code zu statements[ihreZählvariable] um.
- Damit Ihre Zählvariable nach jeder User-Interaktion um eins erhöht wird, müssen Sie in beiden onPressed-Methoden den Code:
onPressed: () {
setState(() {
scoreKeeper.add(Icon(Icons.check, color: Colors.green));
});
},
durch folgenden Code ersetzen:
onPressed: () {
setState(() {
ihreZählvariable++;
});
},
(Hinweis: Der Code ihreZählvariable++; entspricht der Kurzschreibweise von ihreZählvariable = ihreZählvariable + 1; )
Nach diesen Anpassungen sollte die App nach jedem mal wenn die Wahr oder Falsch Schaltfläche gedrückt wird, zur nächsten Aussage springen. Aber nach drei Klicks erscheint die folgende Fehlermeldung im iOS- oder Android Emulator.
In der Debug-Konsole steht zusätzlich die Meldung: 'RangeError (index): Invalid value: Not in inclusive range 0..2: 3' Der Fehler kommt dadurch zustande, da auf ein Listenelement (Index 3) zugegriffen werden will, dass zu diesem Zeitpunkt gar nicht existiert. Deshalb teilt Ihnen die Debug-Konsole mit, dass der Index ausserhalb des Bereichs liegt.
Falls Sie die App über Google Chrome ausführen, kommt in der Debug-Konsole von VS Code die Fehlermeldung: RangeError (index): Index out of range: index should be less than 3.
Mit einem Hot-Restart lässt sich die Zählvariable wieder auf 0 zurücksetzen und Sie könnten wieder drei Mal auf eine der Schaltflächen tippen, bis die App wieder mit der gleichen Fehlermeldung abstürzt. Diesen Fehler werden Sie in Kürze korrigieren.
Hinweis: Über das grüne Icon lässt sich im Debug-Modus ein Hot-Restart ausführen.
Übung
Liste mit Antworten erstellen
Fügen Sie nach der Zählvariable eine neue Liste vom Typ bool ein, die die zugehörigen Antworten zu den drei Smartphone-Mythen von oben enthält, also [false, false, true]. Hinweis: Beim gleichen Index sollten die Aussagen mit den korrekten Antworten übereinstimmen. Die erste Aussage in der statements-Liste lautete 'Geöffnete Apps brauchen viel Akku.' und somit sollte der erste boolesche Ausdruck in der Liste der Antworten false lauten.
Antworten mit Verzweigungen überprüfen
Jetzt, wo Sie eine Liste mit den korrekten Antworten besitzen, müssen Sie nur noch prüfen, ob die gewählte Schaltfläche der richtigen Antwort entspricht. Wir lösen das mit einer if-else-Verzweigung.
Theorie
Verzweigungen
Die Syntax für if-Anweisungen unterscheidet sich in der Programmiersprache Dart nur geringfügig der von Python.
if (boolescheAusdruck) {
// dieser Code wird ausgeführt, wenn der boolesche Ausdruck wahr ist.
} else {
// dieser Code wird ausgeführt, wenn der boolesche Ausdruck falsch ist.
}
Auf ein if– kann ein optionaler else-Block folgen. Der else-Block wird ausgeführt, wenn der vom if-Block getestete boolesche Ausdruck false ergibt.
In unserem Flutter-Projekt erstellen wir in der onPressed-Methode der Wahr-Schaltfläche die Variable correctAnswer vom Typ bool, mit der wir jeweils auf das entsprechende Listenelement der Liste mit den Antworten verweisen. Innerhalb der if-Anweisung prüfen wir mit dem Vergleich correctAnswer == true, ob die gewählte Antwort korrekt ist. Falls die Antwort korrekt ist erweitern wir die Liste scoreKeeper mit einem grünen Haken-Icon. Falls die Antwort nicht korrekt ausgewählt wurde, sollte scoreKeeper mit einem roten Kreuz-Icon erweitert werden.
onPressed: () {
bool correctAnswer = answers[statementCounter];
if (correctAnswer == true) {
scoreKeeper.add(Icon(Icons.check, color: Colors.green));
} else {
scoreKeeper.add(Icon(Icons.close, color: Colors.red));
}
setState(() {
statementCounter++;
});
Analog wird die onPressed-Methode für die Falsch-Schaltfläche angepasst. Dort muss die Variable correctAnswer dem Wert false entsprechen, damit die if-Anweisung erfüllt wird und ein grünes Haken-Icon erzeugt wird.
onPressed: () {
bool correctAnswer = answers[statementCounter];
if (correctAnswer == false) {
scoreKeeper.add(Icon(Icons.check, color: Colors.green));
} else {
scoreKeeper.add(Icon(Icons.close, color: Colors.red));
}
setState(() {
statementCounter++;
});
Nach diesen Anpassungen sollte es Ihnen möglich sein die ersten beiden Fragen zu beantworten und Punkte in Form von grünen Haken zu sammeln. Da der RangeError-Fehler noch nicht behoben worden ist, stürzt die App nach der dritten Aussage immer noch ab.
Falls bei Ihnen etwas nicht geklappt haben sollte, können Sie hier den kompletten Code bis zum aktuellen Stand kopieren.
import 'package:flutter/material.dart';
void main() {
runApp(QuizApp());
}
class QuizApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.grey.shade900,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: QuizPage(),
),
),
),
);
}
}
class QuizPage extends StatefulWidget {
@override
_QuizPageState createState() => _QuizPageState();
}
// 1
class _QuizPageState extends State {
List<Icon> scoreKeeper = [];
List statements = [
'Geöffnete Apps brauchen viel Akku.',
'Eine Kamera mit mehr Megapixeln resultiert in besseren Bildern.',
'5G frisst nicht mehr Daten als 4G.'
];
int statementCounter = 0;
List<bool> answers = [false, false, true];
@override
Widget build(BuildContext context) {
// 2
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 3
Expanded(
flex: 5,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
statements[0],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
),
),
),
),
),
// 3
Expanded(
child: Padding(
padding: EdgeInsets.all(15.0),
child: TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.green),
child: Text(
'Wahr',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
onPressed: () {
bool correctAnswer = answers[statementCounter];
if (correctAnswer == true) {
scoreKeeper.add(Icon(Icons.check, color: Colors.green));
} else {
scoreKeeper.add(Icon(Icons.close, color: Colors.red));
}
setState(() {
statementCounter++;
});
},
),
),
),
// 3
Expanded(
child: Padding(
padding: EdgeInsets.all(15.0),
child: TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.red),
child: Text(
'Falsch',
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
onPressed: () {
bool correctAnswer = answers[statementCounter];
if (correctAnswer == false) {
scoreKeeper.add(Icon(Icons.check, color: Colors.green));
} else {
scoreKeeper.add(Icon(Icons.close, color: Colors.red));
}
setState(() {
statementCounter++;
});
},
),
),
),
// 1
Row(
children: scoreKeeper,
)
],
);
}
}
Damit Ihr Code ein bisschen geordneter daherkommt, werden Sie im nächsten Abschnitt für Ihre Aussagen und Antworten eine eigene Klasse kreieren. Dabei wiederholen Sie was Klassen und Objekte sind.