Track switch selected in flutter
I wrote the code below for the quiz app, but got stuck looking for a way to compare the selected radio button with the correct ans, and also delay moving to the next question just enough to visually indicate the choice made. Tried using switch statement and _counter variable but results in error
The following NoSuchMethodError was thrown while handling a gesture:
I/flutter (28574): The method '[]' was called on null.
I am not knowledgeable enough to understand where / what the error might mean or what might be wrong with this approach (switch statement). Any corrections / directions / hints would be appreciated. Thank.
import 'dart:async';
import 'package:flutter/material.dart';
Map<String, Map<String, String>> questionBank = {
"1": {
"question": "What is the capital of Canada?",
"ans1": "Toronto",
"ans2": "Montreal",
"ans3": "Ottawa",
"ans4": "Vancouver",
"coAns": "Ottawa"
},
"2": {
"question": "What is the capital of the United States of America?",
"ans1": "New York",
"ans2": "California",
"ans3": "Texas",
"ans4": "Washington DC",
"coAns": "Washington DC"
},
"3": {
"question": "What is the capital of Nigeria?",
"ans1": "Abuja",
"ans2": "Lagos",
"ans3": "Port Harcourt",
"ans4": "Makurdi",
"coAns": "Abuja"
},
"4": {
"question": "What is the capital of England?",
"ans1": "Britain",
"ans2": "Scotland",
"ans3": "London",
"ans4": "Edinburgh",
"coAns": "London"
},
"5": {
"question": "What is the capital of China?",
"ans1": "Beijing",
"ans2": "Shanghai",
"ans3": "Tianjin",
"ans4": "Taiwan",
"coAns": "Beijing"
},
};
void main() {
runApp(new _questionDisplay());
}
class _questionDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(home: new QuestDis());
}
}
class QuestDis extends StatefulWidget {
QuestDis({Key key}) : super(key: key);
@override
_QuestDisState createState() => new _QuestDisState();
}
class _QuestDisState extends State<QuestDis> {
@override
var _counter = 1;
var bkgrdColor = Colors.blue[50];
int radioValue = 0;
int ans1Value = 1;
int ans2Value = 2;
int ans3Value = 3;
int ans4Value = 4;
void handleRadioValueChanged(int value) {
setState(() {
radioValue = value;
/*
switch (radioValue) {
case 1:
bkgrdColor = (questionBank[_counter]["coAns"] ==
questionBank[_counter][ans1Value])
? Colors.green[50]
: Colors.red[50];
break;
case 2:
bkgrdColor = (questionBank[_counter]["coAns"] ==
questionBank[_counter][ans2Value])
? Colors.green[50]
: Colors.red[50];
break;
case 3:
bkgrdColor = (questionBank[_counter]["coAns"] ==
questionBank[_counter][ans3Value])
? Colors.green[50]
: Colors.red[50];
break;
case 4:
bkgrdColor = (questionBank[_counter]["coAns"] ==
questionBank[_counter][ans4Value])
? Colors.green[50]
: Colors.red[50];
break;
}
*/
_counter++;
radioValue = 0;
});
}
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new IconButton(icon: new Icon(Icons.menu), onPressed: null),
title: new Text('quizApp'),
),
body: new Container(
child: new Column(
children: [
new Expanded(
child: new Container(
child: new Column(
children: [
new Expanded(
child: new Container(
child: new Card(
color: bkgrdColor,
child: new Row(
children: <Widget>[
new Text(
"${questionBank[_counter.toString()]["question"]}"),
],
),
),
),
),
new Expanded(
child: new Container(
child: new Card(
child: new Column(
children: [
new Row(
children: <Widget>[
new Radio<int>(
value: ans1Value,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Text(
"${questionBank[_counter.toString()]["ans1"]}")
],
),
new Divider(),
new Row(
children: <Widget>[
new Radio<int>(
value: ans2Value,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Text(
"${questionBank[_counter.toString()]["ans2"]}")
],
),
new Divider(),
new Row(
children: <Widget>[
new Radio<int>(
value: ans3Value,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Text(
"${questionBank[_counter.toString()]["ans3"]}")
],
),
new Divider(),
new Row(
children: <Widget>[
new Radio<int>(
value: ans4Value,
groupValue: radioValue,
onChanged: handleRadioValueChanged),
new Text(
"${questionBank[_counter.toString()]["ans4"]}")
],
),
],
),
),
),
),
],
),
),
),
],
),
),
);
}
}
source to share
If I were you, I would actually create a question object (don't take this for granted, I'm writing this quickly on my ipad so the syntax might be out of place ...):
class Question {
String question;
List<String> answers;
String correctAnswer;
Question(question, answers, correctAnswer);
}
Now you can use the object to create a list of questions:
List<Question> questions = [
new Question("What is 2+2", ["2", "3", "4"], "4"),
// create as many questions as you want
];
you can keep your counter variable and actually use it as an index.
Let's say you manage to get the answer the user selected on the line named selectedAnswer. In your setState (), I would do something like this:
if (chosenAnswer == questions[_counter].correctAnswer){
// answer was correct
} else {
// answer is false
}
// and dont forget to increment your counter
_counter++;
To display the questions and answers to the user, you can again use the counter variable as an index and access every possible answer in the Question object that is stored in the list.
I hope I can help a little
source to share