skip to Main Content

My code is basic as my question:

Why I am not able to add the answers after click on Radio Button and also print the answer on the console with this code?

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyQuestion(),
    );
  }
}

class MyQuestion extends StatefulWidget {
  const MyQuestion({super.key});

  @override
  State<MyQuestion> createState() => _MyQuestionState();
}

class _MyQuestionState extends State<MyQuestion> {
  final List<String> selectedAnswers = [];

  void chooseAnswer(String answer) {
    setState(() {
      selectedAnswers.add(answer);
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Padding(
        padding: EdgeInsets.all(8.0),
        child: FirstScreen(),
      ),
    );
  }
}

class FirstScreen extends StatefulWidget {
  const FirstScreen({super.key});

  @override
  State<FirstScreen> createState() => _FirstScreenState();
}

class _FirstScreenState extends State<FirstScreen> {
  int selectedOption = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Seja Bem-Vindo (a) ao QuestionĂ¡rio TAS-20',
          style: TextStyle(
            color: Colors.amber,
            fontSize: 16,
          ),
        ),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const MyQuestion(),
              ),
            );
          },
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(6.0),
        child: ListView(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Radio(
                  value: 1,
                  groupValue: selectedOption,
                  onChanged: (value) {
                    setState(() {
                      selectedOption = value as int;
                      _MyQuestionState().chooseAnswer(value as String);
                    });
                  },
                ),
                Radio(
                  value: 2,
                  groupValue: selectedOption,
                  onChanged: (value) {
                    setState(() {
                      selectedOption = value as int;
                      _MyQuestionState().chooseAnswer(value as String);
                    });
                  },
                ),
                Radio(
                  value: 3,
                  groupValue: selectedOption,
                  onChanged: (value) {
                    setState(() {
                      selectedOption = value as int;
                      _MyQuestionState().chooseAnswer(value as String);
                    });
                  },
                ),
                Radio(
                  value: 4,
                  groupValue: selectedOption,
                  onChanged: (value) {
                    setState(() {
                      selectedOption = value as int;
                      _MyQuestionState().chooseAnswer(value as String);
                    });
                  },
                ),
              ],
            ),
            const Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Text('Answer 1'),
                Text('Answer 2'),
                Text('Answer 3'),
                Text('Answer 4')
              ],
            ),
            ElevatedButton(
              onPressed: () {},
              child: const Text('Next'),
            ),
          ],
        ),
      ),
    );
  }
}

I think my main problem is how to use this chunk of code into FirstScreen statefull Widget:

 final List<String> selectedAnswers = [];

  void chooseAnswer(String answer) {
    setState(() {
      selectedAnswers.add(answer);
    });
  }

I tried to include _MyQuestionState().chooseAnswer(value as String); at onChanged argument but its not working.

Also at the same time I answer I am not able to include as a print on the console the answer that the user chosed.

2

Answers


  1. There are several things that need to be fixed:

    1. You can’t convert an int to a String by using the type cast as String. You should use the toString method instead, so change value as String to value.toString().
    2. When you call _MyQuestionState().chooseAnswer, you’re actually creating a new instance of _MyQuestionState(), and not controlling the existing state. If you want to be able to call the chooseAnswer from FirstScreen, you should pass the callback in _MyQuestionState like this:
      Widget build(BuildContext context) {
        return Scaffold( // (1) remove the 'const'
          body: Padding(
            padding: EdgeInsets.all(8.0),
            child: FirstScreen(chooseAnswer: chooseAnswer), // (2) pass the 'chooseAnswer' method
          ),
        );
      }
      

      In FirstScreen, add the chooseAnswer parameter:

      class FirstScreen extends StatefulWidget {
        const FirstScreen({super.key, required this.chooseAnswer}); // (1) add it in the constructor
      
        final void Function(String) chooseAnswer; // (2) add the property
      
        @override
        State<FirstScreen> createState() => _FirstScreenState();
      }
      

      After that, change the call of _MyQuestionState().chooseAnswer to widget.chooseAnswer. Additionally, you don’t need to put this call inside setState, so your onChanged callback should look like this:

      onChanged: (value) {
        setState(() {
          selectedOption = value!; // (1) to convert 'int?' to 'int', just put '!' after the value
        });
        widget.chooseAnswer(value.toString()); // (2) call 'chooseAnswer' like this and move it outside the setState
      }
      

    FULL CODE

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: MyQuestion(),
        );
      }
    }
    
    class MyQuestion extends StatefulWidget {
      const MyQuestion({super.key});
    
      @override
      State<MyQuestion> createState() => _MyQuestionState();
    }
    
    class _MyQuestionState extends State<MyQuestion> {
      final List<String> selectedAnswers = [];
    
      void chooseAnswer(String answer) {
        setState(() {
          selectedAnswers.add(answer);
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Padding(
            padding: EdgeInsets.all(8.0),
            child: FirstScreen(chooseAnswer: chooseAnswer),
          ),
        );
      }
    }
    
    class FirstScreen extends StatefulWidget {
      const FirstScreen({super.key, required this.chooseAnswer});
    
      final void Function(String) chooseAnswer;
    
      @override
      State<FirstScreen> createState() => _FirstScreenState();
    }
    
    class _FirstScreenState extends State<FirstScreen> {
      int selectedOption = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text(
              'Seja Bem-Vindo (a) ao QuestionĂ¡rio TAS-20',
              style: TextStyle(
                color: Colors.amber,
                fontSize: 16,
              ),
            ),
            leading: IconButton(
              icon: const Icon(Icons.arrow_back),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => const MyQuestion(),
                  ),
                );
              },
            ),
          ),
          body: Padding(
            padding: const EdgeInsets.all(6.0),
            child: ListView(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Radio(
                      value: 1,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        setState(() {
                          selectedOption = value!;
                        });
                        widget.chooseAnswer(value.toString());
                      },
                    ),
                    Radio(
                      value: 2,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        setState(() {
                          selectedOption = value!;
                        });
                        widget.chooseAnswer(value.toString());
                      },
                    ),
                    Radio(
                      value: 3,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        setState(() {
                          selectedOption = value!;
                        });
                        widget.chooseAnswer(value.toString());
                      },
                    ),
                    Radio(
                      value: 4,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        setState(() {
                          selectedOption = value!;
                        });
                        widget.chooseAnswer(value.toString());
                      },
                    ),
                  ],
                ),
                const Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('Answer 1'),
                    Text('Answer 2'),
                    Text('Answer 3'),
                    Text('Answer 4')
                  ],
                ),
                ElevatedButton(
                  onPressed: () {},
                  child: const Text('Next'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    
    Login or Signup to reply.
  2. First off, if you run your code, you’ll see an erorr:

    Expected a value of type 'String', but got one of type 'int'
    

    This is because in your code, you are doing:

    selectedOption = value as int; // int over here
    _MyQuestionState().chooseAnswer(value as String); // using the `int` but it's really a String
    

    value is an int, not a String, as I have commented

    To fix the issue just call .toString:

    selectedOption = value as int;
    _MyQuestionState().chooseAnswer(value.toString());
    

    that fixes problem 1

    But then, if you run your code again, you’ll encounter another problem once selecting a checkbox:

    setState() called in constructor: _MyQuestionState#4077c(lifecycle state: created, no widget, not mounted)
    

    This is because the Widget is not yet mounted/created. So, to solve the issue, you can use a short deelay:

      Future.delayed(const Duration(milliseconds: 1), () { // --> Use a delay
          setState(() {
            selectedOption = value as int;
            _MyQuestionState().chooseAnswer(value.toString());
          });
        });
    

    Also, you should remove the setState from choooseAnswer

      void chooseAnswer(String answer) {
        setState(() { // <-- remove this
          selectedAnswers.add(answer);
        });
      }
    

    and call it in the onChanged.

    Your complete working code should look like:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: MyQuestion(),
        );
      }
    }
    
    class MyQuestion extends StatefulWidget {
      const MyQuestion({super.key});
    
      @override
      State<MyQuestion> createState() => _MyQuestionState();
    }
    
    class _MyQuestionState extends State<MyQuestion> {
      final List<String> selectedAnswers = [];
    
      void chooseAnswer(String answer) {
        selectedAnswers.add(answer);
      }
    
      @override
      Widget build(BuildContext context) {
        return const Scaffold(
          body: Padding(
            padding: EdgeInsets.all(8.0),
            child: FirstScreen(),
          ),
        );
      }
    }
    
    class FirstScreen extends StatefulWidget {
      const FirstScreen({super.key});
    
      @override
      State<FirstScreen> createState() => _FirstScreenState();
    }
    
    class _FirstScreenState extends State<FirstScreen> {
      int selectedOption = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text(
              'Seja Bem-Vindo (a) ao QuestionĂ¡rio TAS-20',
              style: TextStyle(
                color: Colors.amber,
                fontSize: 16,
              ),
            ),
            leading: IconButton(
              icon: const Icon(Icons.arrow_back),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => const MyQuestion(),
                  ),
                );
              },
            ),
          ),
          body: Padding(
            padding: const EdgeInsets.all(6.0),
            child: ListView(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Radio(
                      value: 1,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        Future.delayed(const Duration(milliseconds: 1), () {
                          setState(() {
                            selectedOption = value as int;
                            _MyQuestionState().chooseAnswer(value.toString());
                          });
                        });
                      },
                    ),
                    Radio(
                      value: 2,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        Future.delayed(const Duration(milliseconds: 1), () {
                          setState(() {
                            selectedOption = value as int;
                            _MyQuestionState().chooseAnswer(value.toString());
                          });
                        });
                      },
                    ),
                    Radio(
                      value: 3,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        Future.delayed(const Duration(milliseconds: 1), () {
                          setState(() {
                            selectedOption = value as int;
                            _MyQuestionState().chooseAnswer(value.toString());
                          });
                        });
                      },
                    ),
                    Radio(
                      value: 4,
                      groupValue: selectedOption,
                      onChanged: (value) {
                        Future.delayed(const Duration(milliseconds: 1), () {
                          setState(() {
                            selectedOption = value as int;
                            _MyQuestionState().chooseAnswer(value.toString());
                          });
                        });
                      },
                    ),
                  ],
                ),
                const Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('Answer 1'),
                    Text('Answer 2'),
                    Text('Answer 3'),
                    Text('Answer 4')
                  ],
                ),
                ElevatedButton(
                  onPressed: () {},
                  child: const Text('Next'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search