maykhid
maykhid

Reputation: 189

How to save individual states for RadioListTile widget using flutter_swiper?

So I'm building this really simple question and answer app, where the screen displays a question and a list of answers in a RadioTileWidget, by swiping a user can see more questions and answers. I used flutter_swipper to achieve changing the questions and answers when swiped. My issue now is that after selecting a particular answer and I swipe to the next question the radio button is still at the position I selected. Obviously, this isn't right. so is there a way I can refresh the state of the RadioListTile after I swipe, but keeping the state of the previously selected answer?

My code:

class QuestionScreen extends StatefulWidget {
  @override
  _QuestionScreenState createState() => _QuestionScreenState();
}

class _QuestionScreenState extends State<QuestionScreen> {
  late SwiperController _controller;
  int ?value;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = SwiperController();
  }

  @override
  Widget build(BuildContext context) {
    return BaseView(
      body: Column(
        children: [

// This is the question and answer container

          Container(
            height: 80.h,
            width: 100.w,
            child: Swiper(
              loop: false,
              controller: _controller,
              itemBuilder: (BuildContext context, int mainIndex) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [

                    // This is the question conatiner

                    Container(
                      
                      width: 100.w,
                      child: Center(
                          child: Text(
                              '(${mainIndex+1}) ${questions[mainIndex]['question']}')),
                    ), 

                    // This is the answer container

                     Container(
                      height: 50.h,
                      child: ListView.builder(
                        itemBuilder: (context, index) {
                          var ans = questions[mainIndex]['answers'];
                          var _ = ans.keys.toList()[index];
                          var _v = ans.values.toList()[index];

                          return RadioListTile( 
                            value: index,
                            groupValue: value,
                            onChanged: (newVal) =>
                                setState(() => value = newVal as int),
                            title: Text('$_ : $_v'),
                          );
                        },
                        itemCount: questions[mainIndex]['answers'].length,
                      ),
                    ), 
                  ],
                );
              },
              itemCount: questions.length,
              pagination: new SwiperPagination(),
              
            ),
          ), 

          // container that holds the previous and Next buttons
          Container(
              // color: Colors.black,
              // height: 20.h,
              width: 100.w,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  TextButton(
                    onPressed: () {
                      _controller.previous();
                    },
                    child: Text('Prev'),
                    style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all<Color>(AppColors.brown)),
                  ),
                  TextButton(
                    onPressed: () {
                      _controller.next();
                    },
                    child: Text('Next'),
                    style: ButtonStyle(
                      backgroundColor:
                          MaterialStateProperty.all<Color>(AppColors.brown),
                    ),
                  ),
                ],
              ))
        ],
      ),
    );
  }
}


So that's it. If there's some part of my explanation that's not understood please do ask me. Thanks in advance.

Upvotes: 1

Views: 310

Answers (1)

maykhid
maykhid

Reputation: 189

After a while, I realized the solution wasn't that far-fetched. I used a List to store the value/state of each radio button on each page that I swiped to.

What I did: I created a list with fixed length (length of the number of questions I had)

late List<dynamic> _stateList;

@override
  void initState() {

    super.initState();
    \\
    _stateList = List<dynamic>.filled(questions.length, '',
        growable:
            false); // on initializing list the list looks like this ['', '', '']

  }

Then I changed RadioListTile like so:

return RadioListTile<String>(
                            value: _,
                            groupValue: _stateList[mainIndex].toString(),
                            onChanged: (newVal) => setState(() {
                              // value = newVal;
                              _stateList[mainIndex] =
                                  newVal; // assign new value to the _stateList[mainIndex]
                              print(_stateList[mainIndex]);
                            }),
                            title: Text('$_ : $_v'),
                          );

That's all I did.

What I just did was store the user's selected value for each page generated. mainIndex is the index of the page generated by Swiper, so for each mainIndex store a value for the answer selected.

Full code:


class QuestionScreen extends StatefulWidget {
  @override
  _QuestionScreenState createState() => _QuestionScreenState();
}

class _QuestionScreenState extends State<QuestionScreen> {
  late SwiperController _controller;
  late List<dynamic>
      _stateList; // to store state for radioSelection for each answered questiion
  String? value;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = SwiperController();
    _stateList = List<dynamic>.filled(questions.length, '',
        growable:
            false); // on initializing list the list looks like this ['', '', '']
  }

  /* 
  Note to self: The _stateList created is to store the value of radio button (for each specific question) and hold
  the answer picked by the user
  */

  @override
  Widget build(BuildContext context) {
    return BaseView(
      body: Column(
        // mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Container(
            height: 80.h,
            width: 100.w,
            child: Swiper(
              loop: false,
              controller: _controller,
              itemBuilder: (BuildContext context, int mainIndex) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    // question
                    Container(
                      // height: 50.h,
                      width: 100.w,
                      child: Center(
                          child: Text(
                              '(${mainIndex + 1}) ${questions[mainIndex]['question']}')),
                    ),
                    // answer

                    Container(
                      height: 50.h,
                      child: ListView.builder(
                        itemBuilder: (context, index) {
                          var ans = questions[mainIndex]['answers'];
                          var _ = ans.keys.toList()[index];
                          var _v = ans.values.toList()[index];
                          return RadioListTile<String>(
                            value: _,
                            groupValue: _stateList[mainIndex].toString(),
                            onChanged: (newVal) => setState(() {
                              // value = newVal;
                              _stateList[mainIndex] =
                                  newVal; // assign new value to the _stateList[mainIndex]
                              print(_stateList[mainIndex]);
                            }),
                            title: Text('$_ : $_v'),
                          );
                        },
                        itemCount: questions[mainIndex]['answers'].length,
                      ),
                    ),
                  ],
                );
              },
              itemCount: questions.length,
              // itemWidth: 300.0,
              // itemHeight: 400.0,
              pagination: new SwiperPagination(),
              // control: new SwiperControl(),
            ),
          ),
          //
          Container(
              // color: Colors.black,
              // height: 20.h,
              width: 100.w,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  TextButton(
                    onPressed: () {
                      _controller.previous();
                      // setState(() {

                      // });
                    },
                    child: Text('Prev'),
                    style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all<Color>(AppColors.brown)),
                  ),
                  TextButton(
                    onPressed: () {
                      _controller.next();
                    },
                    child: Text('Next'),
                    style: ButtonStyle(
                      backgroundColor:
                          MaterialStateProperty.all<Color>(AppColors.brown),
                    ),
                  ),
                ],
              ))
        ],
      ),
    );
  }
}

Upvotes: 1

Related Questions