Flutter 弹出对话框不会在 setState() 上更新

我遇到了颤振问题,当用户按下特定按钮时,我创建了一个弹出对话框,他可以在其中选中复选框。

问题是 setState() 上的复选框没有更新,就在我关闭弹出对话框并再次打开它之后,我可以看到我检查了它们。

我在弹出对话框中有 setState() 不好?我似乎看不出问题出在哪里。

这是代码:

编辑:更新代码:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class AlwaysDisabledFocusNode extends FocusNode {
  @override
  bool get hasFocus => false;
}

class MultiLanguagePopupProduct extends StatefulWidget {
  @override
  _MultiLanguagePopupProductState createState() =>
      _MultiLanguagePopupProductState();
}

class _MultiLanguagePopupProductState extends State<MultiLanguagePopupProduct> {
  int selectedIndex = -1;

  String text = '';

  @override
  Widget build(BuildContext context) {
    return StatefulBuilder(
        builder: (context, setState) {
          return Container(
            child: TextField(
              focusNode: AlwaysDisabledFocusNode(),
              enableInteractiveSelection: false,
              decoration: InputDecoration(
                suffixIcon: IconButton(
                  icon: Icon(FontAwesomeIcons.boxOpen),
                ),
                labelText: 'Name and language: $text ',
                labelStyle:
                TextStyle(
                    fontWeight: FontWeight.bold, color: Colors.lightGreen),
              ),
              onTap: () =>
                  showDialog(
                    context: context,
                    builder: (context) {
                      return AlertDialog(
                        scrollable: true,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10),
                        ),
                        title: Text('Multilanguage for product'),
                        content: Column(
                          children: <Widget>[
                            DataTable(
                              onSelectAll: (val) {
                                setState(() {
                                  selectedIndex = -1;
                                  text = '';
                                });
                              },
                              columns: [
                                DataColumn(label: Text('Language')),
                                DataColumn(label: Text('Translation')),
                              ],
                              rows: [
                                DataRow(
                                    selected: 0 == selectedIndex,
                                    onSelectChanged: (val) {
                                      setState(() {
                                        selectedIndex = 0;
                                        text = 'RO';
                                      }
                                      );
                                    },
                                    cells: [
                                      DataCell(
                                          Text(
                                            "RO",
                                            textAlign: TextAlign.left,
                                            style: TextStyle(
                                                fontWeight: FontWeight.bold),
                                          ), onTap: () {
                                        setState(() {
                                          selectedIndex = 0;
                                          text = 'RO';
                                          print('RO is clicked');
                                        });
                                      }),
                                      DataCell(
                                        TextField(
                                          decoration: InputDecoration(
                                              border: InputBorder.none,
                                              hintText: 'paine'),
                                        ),
                                      ),
                                    ]),
                                DataRow(
                                    selected: 1 == selectedIndex,
                                    onSelectChanged: (val) {
                                      setState(() {
                                        selectedIndex = 1;
                                        text = 'EN';
                                      });
                                    },
                                    cells: [
                                      DataCell(
                                          Text(
                                            "EN",
                                            textAlign: TextAlign.left,
                                            style: TextStyle(
                                                fontWeight: FontWeight.bold),
                                          ), onTap: () {
                                        setState(() {
                                          selectedIndex = 1;
                                          text = 'EN';
                                          print('EN is clicked');
                                        });
                                      }),
                                      DataCell(
                                        TextField(
                                          decoration: InputDecoration(
                                              border: InputBorder.none,
                                              hintText: 'bread'),
                                        ),
                                      ),
                                    ]),
                                DataRow(
                                    selected: 2 == selectedIndex,
                                    onSelectChanged: (val) {
                                      setState(() {
                                        selectedIndex = 2;
                                        text = 'FR';
                                      });
                                    },
                                    cells: [
                                      DataCell(
                                          Text(
                                            "FR",
                                            textAlign: TextAlign.left,
                                            style: TextStyle(
                                                fontWeight: FontWeight.bold),
                                          ), onTap: () {
                                        setState(() {
                                          selectedIndex = 2;
                                          text = 'FR';
                                          print('FR is clicked');
                                        });
                                      }),
                                      DataCell(
                                        TextField(
                                          decoration: InputDecoration(
                                              border: InputBorder.none,
                                              hintText: 'pain'),
                                        ),
                                      ),
                                    ]),
                              ],
                            ),
                          ],
                        ),
                        actions: <Widget>[
                          FlatButton(
                              onPressed: () => Navigator.of(context).pop(),
                              child: Text('OK')),
                          FlatButton(
                              onPressed: () => Navigator.of(context).pop(),
                              child: Text('CANCEL')),
                        ],
                      );
                    },
                  ),
            ),
          );
        },
    );
  }
}
stack overflow Flutter pop up dialog doesn't update on setState()
原文答案
author avatar

接受的答案

StatefulBuilder 是正确的答案。但是,您将其放在错误的位置。你应该把它放在 showDialog() 里面,而不是外面。我已经在 codepen 中实现了您的代码。一探究竟。

showDialog(
  context: context,
  builder: (context) {
    return StatefulBuilder(
      builder: (context, setStateForDialog) {
        return AlertDialog();
      }
    );
  }
)

答案:

作者头像

要仅在其中更新 Widgets,请使用 StatefulBuilder 在 Dialog 中使用 setState

 showDialog(
  context: context,
   builder: (context) {
   String contentText = "Content of Dialog";
    return StatefulBuilder(
     builder: (context, setState) {
      return AlertDialog(
      title: Text("Title Text"),
      content: Text(contentText),
      actions: <Widget>[
        FlatButton(
          onPressed: () => Navigator.pop(context),
          child: Text("Cancel"),
        ),
        FlatButton(
          onPressed: () {
            setState(() {
              contentText = "Changed Content of your Dialog";
            });
          },
          child: Text("Change Text"),
         ),
        ],
      );
    },
   );
  },
);
作者头像

您需要在 showDialog 中使用 StatefulBuilder。检查下面的代码,也许你从这里明白了。

showDialog(
  context: context,
  builder: (context) {
    return StatefulBuilder(
      builder: (BuildContext context, setState) {
        return AlertDialog(
          icon: const Icon(
            Icons.reviews,
            size: 40,
          ),
          iconColor: secondaryColor,
          title: const Text(
            'Add a Review',
            style: TextStyle(
              fontSize: 24,
            ),
          ),
          actions: [
            Padding(
              padding: const EdgeInsets.symmetric(
                horizontal: 4,
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  TextIconButton(
                    text: 'Submit',
                    icon: Icons.arrow_right,
                    onTap: () {},
                  ),
                  TextIconButton(
                    text: 'Close',
                    icon: Icons.clear,
                    onTap: () {
                      Navigator.of(context).pop();
                    },
                  )
                ],
              ),
            ),
          ],
          content: Container(
            width: width * 0.8,
            child: SingleChildScrollView(
              child: Column(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Row(
                        children: [
                          InkWell(
                            onTap: () {
                              setState(() {
                                rating = 1;
                              });
                            },
                            child: ratingStar(rating > 0),
                          ),
                          InkWell(
                              onTap: () {
                                setState(() {
                                  rating = 2;
                                });
                              },
                              child: ratingStar(rating > 1)),
                          InkWell(
                              onTap: () {
                                setState(() {
                                  rating = 3;
                                });
                              },
                              child: ratingStar(rating > 2)),
                          InkWell(
                            onTap: () {
                              setState(() {
                                rating = 4;
                              });
                            },
                            child: ratingStar(rating > 3),
                          ),
                          InkWell(
                            onTap: () {
                              setState(() {
                                rating = 5;
                              });
                            },
                            child: ratingStar(rating > 4),
                          ),
                        ],
                      ),
                      InkWell(
                        onTap: () {
                          setState(() {
                            rating = 0;
                          });
                        },
                        child: const Icon(
                          Icons.clear,
                        ),
                      ),
                    ],
                  ),
                  SizedBox(
                    height: height * 0.01,
                  ),
                  InputField(
                    hintText: 'Review text ...',
                    icon: Icons.message,
                    inputController: reviewController,
                    maxLines: 5,
                  )
                ],
              ),
            ),
          ),
        );
      },
    );
  },
);