Reputation: 669
I have a question palette in the flutter screen, where a user taps on the question number that question is shown, and a next button to display the next question.
If I am traversing between the questions using the question palette it's working fine but when I click next button, it does not turn the question number on the palette to green(I want that question number to get green) and also it does not return the next question but the loop iterates. As after I press the button for some time, it says that there are no next questions as I have set this message when the loop ends.
Here is my code:
class quizpage extends StatefulWidget{
var questions,surveyid;
quizpage(this.questions,this.surveyid);
//quizpage({Key key, @required this.questions}) : super(key : key);
@override
_quizpageState createState() => _quizpageState(questions,surveyid);
}
class _quizpageState extends State<quizpage> with SingleTickerProviderStateMixin {
var questions,surveyid;
_quizpageState(this.questions,this.surveyid);
int i = 0;
int flag = 0;
int counter = 0;
int length;
Map<String, Color> btncolor = {
"1" : Colors.grey,
"2" : Colors.grey,
"3" : Colors.grey,
"4" : Colors.grey,
"5" : Colors.grey,
"6" : Colors.grey,
"7" : Colors.grey,
"8" : Colors.grey,
"9" : Colors.grey,
};
final answercontroller = TextEditingController();
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown, DeviceOrientation.portraitUp
]);
SizeConfig().init(context);
// TODO: implement build
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SizedBox(
height: 600,
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Numberofquestion()
],
),
),
Expanded(
flex: 4,
child: Center(
child: Container(
width: 400,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 250,
child: Material(
elevation: 5,
color: Colors.deepOrange,
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
child: TextField(
enabled: false,
maxLines: 6,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: questions[i]
),
style: TextStyle(
fontSize: 20,
color: Colors.black
),
),
),
)
],
),
),
)
),
Expanded(
flex: 2,
child: Center(
child: Container(
width: 300,
height: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 250,
child: Material(
elevation: 2,
color: Colors.deepOrange,
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
child: TextField(
controller: answercontroller,
maxLines: 1,
//enabled: false,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Answer'
),
style: TextStyle(
fontSize: 20,
color: Colors.black
),
),
),
),
]
)
)
)
),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(onPressed: SkipQuestion,
color: Colors.deepOrange,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('Skip',
style: TextStyle(
fontSize: 20
),
),
),
RaisedButton(onPressed: NextQuestion,
color: Colors.green,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('Next',
style: TextStyle(
fontSize: 20
),
),
),
],
),
],
),
)
)
],
),
),
),
),
);
}
@override
void setState(fn) {
// TODO: implement setState
super.setState(fn);
if(btncolor[(i+1).toString()] == Colors.deepOrange){
btncolor[(i+1).toString()] = Colors.purple;
flag = 1;
}
else if(btncolor[(i+1).toString()] == Colors.green){
btncolor[(i+1).toString()] = Colors.purple;
flag = 2;
}
else{
btncolor[(i+1).toString()] = Colors.purple;
}
}
void NextQuestion() async {
if(answercontroller.text.length == 0){
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Alert'),
content: Text(
'Please enter an answer.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
}
else{
setState(() async {
if(i < (questions.length - 1)){
// ignore: unnecessary_statements
btncolor[(i+1).toString()] = Colors.green;
i++;
}
else{
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Alert'),
content: Text(
'There are no next questions.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
}
});
}
}
@override
void initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
void SkipQuestion() {
setState(() {
if(i < (questions.length - 1)){
// ignore: unnecessary_statements
btncolor[(i+1).toString()] = Colors.deepOrange;
i++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(surveyid),
));
}
});
}
void ChooseQuestion() {
setState(() {
if(i < (questions.length)){
for(int k =0; k< (questions.length); k++){
if(k != i){
if(btncolor[(k+1).toString()] == Colors.purple){
if(flag == 1){
btncolor[(k+1).toString()] = Colors.red;
flag =0;
}
else if(flag == 2){
btncolor[(k+1).toString()] = Colors.green;
flag =0;
}
else{
btncolor[(k+1).toString()] = Colors.grey;
}
}
}
else{
if(btncolor[(k+1).toString()] == Colors.purple){
if(flag == 1){
btncolor[(k+1).toString()] = Colors.red;
}
else if(flag == 2){
btncolor[(k+1).toString()] = Colors.green;
flag =0;
}
else{
btncolor[(k+1).toString()] = Colors.grey;
}
}
}
}
//i++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(surveyid),
));
}
});
}
Widget Numberofquestion() {
if(questions.length == 9){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 0;
ChooseQuestion();
},
color: btncolor["1"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text("1",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 1;
ChooseQuestion();
},
color: btncolor["2"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('2',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 2;
ChooseQuestion();
},
color: btncolor["3"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('3',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 3;
ChooseQuestion();
},
color: btncolor["4"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('4',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
],
);
}
}
}
Here, questions is the array which stores the question.
When I am using the 'Skip' button, the setState works perfectly but when I am using 'Next' button the setState is not working.
Can someone help me with this please?
Upvotes: 1
Views: 4730
Reputation: 3966
I'd say that you're manipulating the state in a wrong way
As docs refers:
@protected
void setState (VoidCallback fn)
The provided callback is immediately called synchronously. It must not return a future (the callback cannot be async), since then it would be unclear when the state was actually being set.
things to note:
You might see the link, hope it's useful
Upvotes: 3
Reputation: 1971
try this
@override
void setState(fn) {
if(btncolor[(i+1).toString()] == Colors.deepOrange){
btncolor[(i+1).toString()] = Colors.purple;
flag = 1;
}
else if(btncolor[(i+1).toString()] == Colors.green){
btncolor[(i+1).toString()] = Colors.purple;
flag = 2;
}
else{
btncolor[(i+1).toString()] = Colors.purple;
}
super.setState(fn);//move here
}
Upvotes: 1