Home > Software design >  Iterating through a list of items with each step awaiting user input before moving on to next item i
Iterating through a list of items with each step awaiting user input before moving on to next item i

Time:01-14

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"];
}

enter image description here

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"];
}
  •  Tags:  
  • Related