I have a list of items that I want to present to the user one-by-one, this being controlled by awaiting user input before showing next item.
To give a contextual example this could be a list of questions that the user has to answer one-by-one. Each question will have question body and a list of options for user to select. They could be presented by a single Card to begin with and once they have selected one of the options the value is captured and the next Card is displayed below
So the super simplified version off what I have is something like this
import 'package:flutter/material.dart';
class QuestionScreen extends StatefulWidget {
QuestionScreen();
@override
_QuestionScreenState createState() => _QuestionScreenState();
}
class _QuestionScreenState extends State<QuestionScreen> {
@override
Widget build(BuildContext context) {
List<Question> listOfQuestions = [
new Question(),
new Question(),
new Question()
];
return Scaffold(
body: Column(
children: [
Text('List Of Questions'),
...listOfQuestions.map((eachQuestion) {
return Card(
elevation: 10,
margin: EdgeInsets.symmetric(
vertical: 5,
horizontal: 10,
),
child: ListTile(
title: Text(eachQuestion.questionText),
subtitle: Row(
children: [
...eachQuestion.listOfOptionsForTheUserToSelect
.map((eachOption) {
return ElevatedButton(
onPressed: () => {},
child: Text(eachOption),
);
}).toList()
],
),
),
);
}).toList()
],
),
);
}
}
class Question {
String questionText = "question";
List<String> listOfOptionsForTheUserToSelect = ["ans1", "ans2"];
}
CodePudding user response:
One solution is to use two lists. A source list with all the questions, and a second list to display the questions as they are answered.
Here is your code updated with a very basic solution as example.
Note I added in a small boolean check so an already answered question can't be answered twice, and also to stop throwing an error once all questions are completed.
import 'package:flutter/material.dart';
class QuestionScreen extends StatefulWidget {
QuestionScreen();
@override
_QuestionScreenState createState() => _QuestionScreenState();
}
class _QuestionScreenState extends State<QuestionScreen> {
List<Question> listOfQuestions = [Question(), Question(), Question()];
List<Question> listOfQuestionsToDisplay = [];
int currentIndex = 0;
initState() {
listOfQuestionsToDisplay.add(listOfQuestions[0]);
super.initState();
}
onQuestionPress({required int index}) {
print('index pressed is $index');
print('current index is $currentIndex');
if (index < currentIndex) {
print('already pressed');
} else if (listOfQuestions.length == listOfQuestionsToDisplay.length) {
print('all questions answered');
} else {
listOfQuestionsToDisplay.add(listOfQuestions[index 1]);
currentIndex ;
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text('List Of Questions'),
...listOfQuestionsToDisplay.map((eachQuestion) {
return Card(
elevation: 10,
margin: EdgeInsets.symmetric(
vertical: 5,
horizontal: 10,
),
child: ListTile(
title: Text(
'${eachQuestion.questionText} Q/NO: ${listOfQuestionsToDisplay.indexOf(eachQuestion)}'),
subtitle: Row(
children: [
...eachQuestion.listOfOptionsForTheUserToSelect
.map((eachOption) {
return ElevatedButton(
onPressed: () => {
onQuestionPress(
index: listOfQuestionsToDisplay
.indexOf(eachQuestion)),
},
child: Text(eachOption),
);
}).toList()
],
),
),
);
}).toList()
],
),
);
}
}
class Question {
String questionText = "question";
List<String> listOfOptionsForTheUserToSelect = ["ans1", "ans2"];
}

