Home > Software design >  Rating system of the app doesn't work properly
Rating system of the app doesn't work properly

Time:09-04

I have this code right here, and what I am trying to do is when I press one of the IconButoons, the text below should change depending on what IconButton was pressed. I have a string variable which is modified in every onPressed function, and this variable is oassed to the Text widget. I made something to happen, but not how I want to. For example, I have to press one IconButton, close the AlertDialog, open it again, and only then see the right text from the IconButton. How can I make that Text appear instantly when I press one of the IconButtons. I will paste the hole class that contains the AlertDialog, this specific part being at the bottom of the class.

class _StartPageState extends State<StartPage> {
  bool isLoading = false;
  String appRate = '';

  @override
  Widget build(BuildContext context) => isLoading
      ?const LoadingPage()
      : Scaffold(
      bottomNavigationBar: BottomAppBar(
        color: Colors.teal[200],
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Spacer(),
            IconButton(
              splashColor: Colors.lightBlueAccent,
              tooltip: 'Help',
              icon: const Icon(Icons.info),
              iconSize: 25,
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => InfoPage()),
                );
              },
            ),
            const Spacer(),
            IconButton(
              splashColor: Colors.lightBlueAccent,
              tooltip: 'Profile',
              icon: const Icon(Icons.account_circle_sharp),
              iconSize: 25,
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ProfilePage()),
                );
              },
            ),
            const Spacer(),
          ],
        ),
      ),
      body: Column(
          children: <Widget>[
            Image.asset('assets/GameLogo_2.png'),
            Container(
              height: 100,
            ),
            SizedBox(
                width: 170,
                height: 80,
                child: ElevatedButton(
                  child: const Text('START!'),
                  onPressed: () async {
                    setState(() => isLoading = true);
                    await Future.delayed(const Duration(seconds: 3));
                    setState(() => isLoading = false);
                    Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => Languagele()),
                    );
                  },
                )
            ),
            Container(
              height: 40,
            ),
            SizedBox(
              height: 50,
              width: 150,
              child: ElevatedButton(
                  onPressed: () {},
                  child: const Text('Add sentences!', textAlign: TextAlign.center,)
              ),
            ),
            Container(
              height: 20,
            ),
            SizedBox(
              height: 50,
              width: 150,
              child: ElevatedButton(
                  onPressed: () {
                    showDialog<String>(
                        barrierDismissible: false,
                        context: context,
                        builder: (BuildContext context) => AlertDialog(
                          backgroundColor: Colors.teal[50],
                          title: const Text('Rate the game', textAlign: TextAlign.center, style: TextStyle(fontSize: 25),),
                          content: SizedBox(
                            height: 80,
                            child: Column(
                              children: <Widget>[
                                Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: <Widget>[
                                    IconButton(
                                        onPressed: () {
                                          appRate = 'Poor';
                                          setState(() {});
                                          },
                                        icon: const Icon(Icons.star, size: 35, color: Colors.teal),
                                    ),
                                    IconButton(
                                        onPressed: () {
                                          appRate = 'Fair';
                                          setState(() {});
                                        },
                                        icon: const Icon(Icons.star, size: 35, color: Colors.teal),
                                    ),
                                    IconButton(
                                        onPressed: () {
                                          appRate = 'Acceptable';
                                          setState(() {});
                                          },
                                        icon: const Icon(Icons.star, size: 35, color: Colors.teal),
                                    ),
                                    IconButton(
                                        onPressed: () {
                                          appRate = 'Good';
                                          setState(() {});
                                          },
                                        icon: const Icon(Icons.star, size: 35, color: Colors.teal),
                                    ),
                                    IconButton(
                                        onPressed: () {
                                          appRate = 'Outstanding';
                                          setState(() {});
                                          },
                                        icon: const Icon(Icons.star, size: 35, color: Colors.teal),
                                    ),
                                  ],
                                ),
                                Text(appRate)
                              ],
                            )
                          ),
                          elevation: 24,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(10),
                          ),
                          actionsAlignment: MainAxisAlignment.spaceAround,
                          actions: <Widget>[
                            TextButton(
                              onPressed: () => Navigator.pop(context),
                              child: const Text('Ok'),
                            ),
                          ],
                        )
                    );
                  },
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: const <Widget>[
                      Text('Rate the app! '),
                      Icon(Icons.star)
                    ],
                  )
              ),
            )
          ]
      ),
      backgroundColor: Colors.white,
    );
}

CodePudding user response:

when you call SetState your screen would change but the dialog would not update, so for that we need to update it manually by wrap your dialog's content with StatefulBuilder , like this:

showDialog<String>(
                        barrierDismissible: false,
                        context: context,
                        builder: (BuildContext context) => AlertDialog(
                              backgroundColor: Colors.teal[50],
                              title: const Text(
                                'Rate the game',
                                textAlign: TextAlign.center,
                                style: TextStyle(fontSize: 25),
                              ),
                              content: StatefulBuilder(
                                  builder: (context, innerSetState) {
                                return SizedBox(
                                    height: 80,
                                    child: Column(
                                      children: <Widget>[
                                        Row(
                                          mainAxisAlignment:
                                              MainAxisAlignment.center,
                                          children: <Widget>[
                                            IconButton(
                                              onPressed: () {
                                                appRate = 'Poor';
                                                setState(() {});
                                                innerSetState(() {});
                                              },
                                              icon: const Icon(Icons.star,
                                                  size: 35, color: Colors.teal),
                                            ),
                                            IconButton(
                                              onPressed: () {
                                                appRate = 'Fair';
                                                setState(() {});
                                                innerSetState(() {});
                                              },
                                              icon: const Icon(Icons.star,
                                                  size: 35, color: Colors.teal),
                                            ),
                                            IconButton(
                                              onPressed: () {
                                                appRate = 'Acceptable';
                                                setState(() {});
                                                innerSetState(() {});
                                              },
                                              icon: const Icon(Icons.star,
                                                  size: 35, color: Colors.teal),
                                            ),
                                            IconButton(
                                              onPressed: () {
                                                appRate = 'Good';
                                                setState(() {});
                                                innerSetState(() {});
                                              },
                                              icon: const Icon(Icons.star,
                                                  size: 35, color: Colors.teal),
                                            ),
                                            IconButton(
                                              onPressed: () {
                                                appRate = 'Outstanding';
                                                setState(() {});
                                                innerSetState(() {});
                                              },
                                              icon: const Icon(Icons.star,
                                                  size: 35, color: Colors.teal),
                                            ),
                                          ],
                                        ),
                                        Text(appRate)
                                      ],
                                    ));
                              }),
                              elevation: 24,
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(10),
                              ),
                              actionsAlignment: MainAxisAlignment.spaceAround,
                              actions: <Widget>[
                                TextButton(
                                  onPressed: () => Navigator.pop(context),
                                  child: const Text('Ok'),
                                ),
                              ],
                            ));

Another tip for cleaner code, try create other widget class and put your dialog builder inside that and pass value like this:

onPressed: () async {
                Future<String?> future = showDialog<String>(
                    barrierDismissible: false,
                    context: context,
                    builder: (BuildContext context) =>
                        YourOtheWidgetClass());

                future.then((value) {
                  if (value != null) {
                    setState(() {
                      appRate = value;
                      setState(() {});
                    });
                  }
                });
              },

and inside you Dialog create variable like appRate and instead of calling setstate to pass it do nothing and pass it through ok button like this:

Navigator.pop(context, appRate);

CodePudding user response:

You have to wrap your AlertDialog inside a StatefulBuilder to update the dialog state.

showDialog<String>(
        barrierDismissible: false,
        context: context,
        builder: (BuildContext context) =>
            StatefulBuilder(builder: (context, alertSetState) {
              return AlertDialog(
                backgroundColor: Colors.teal[50],
                title: const Text(
                  'Rate the game',
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 25),
                ),
                content: SizedBox(
                    height: 80,
                    child: Column(
                      children: <Widget>[
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            IconButton(
                              onPressed: () {
                                appRate = 'Poor';
                                alertSetState(() {});
                              },
                              icon: const Icon(Icons.star,
                                  size: 35, color: Colors.teal),
                            ),
                            IconButton(
                              onPressed: () {
                                appRate = 'Fair';
                                alertSetState(() {});
                              },
                              icon: const Icon(Icons.star,
                                  size: 35, color: Colors.teal),
                            ),
                            IconButton(
                              onPressed: () {
                                appRate = 'Acceptable';
                                alertSetState(() {});
                              },
                              icon: const Icon(Icons.star,
                                  size: 35, color: Colors.teal),
                            ),
                            IconButton(
                              onPressed: () {
                                appRate = 'Good';
                                alertSetState(() {});
                              },
                              icon: const Icon(Icons.star,
                                  size: 35, color: Colors.teal),
                            ),
                            IconButton(
                              onPressed: () {
                                appRate = 'Outstanding';
                                alertSetState(() {});
                              },
                              icon: const Icon(Icons.star,
                                  size: 35, color: Colors.teal),
                            ),
                          ],
                        ),
                        Text(appRate)
                      ],
                    )),
                elevation: 24,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                actionsAlignment: MainAxisAlignment.spaceAround,
                actions: <Widget>[
                  TextButton(
                    onPressed: () => Navigator.pop(context),
                    child: const Text('Ok'),
                  ),
                ],
              );
            }));
  • Related