Setstate() 无法更新 AlertDialog 中的 suffixIcon ? - 颤振

Posted

技术标签:

【中文标题】Setstate() 无法更新 AlertDialog 中的 suffixIcon ? - 颤振【英文标题】:Setstate() not working to update suffixIcon inside AlertDialog ? - Flutter 【发布时间】:2021-10-20 18:14:00 【问题描述】:

我正在尝试为 TextFormField 的 InputDecoration 更新 Form 中的 suffixIcon,以通过 onChange 函数检查给定字符串的长度,但没有更新。另外,我在 Textcontroller 上进行了测试,以便在长度 >= 8 时给它赋值,我希望我能对这个问题给出一个好主意。提前感谢您的解决方案。

import 'package:flutter/material.dart';

bulidDialogChangePass() 
  return DialogPass();


class DialogPass extends StatefulWidget 
  const DialogPass(Key? key) : super(key: key);

  @override
  State<StatefulWidget> createState() 
    return DialogPassState();
  


class DialogPassState extends State<DialogPass> 
  TextEditingController _fPasswordValue = TextEditingController();
  TextEditingController _sPasswordValue = TextEditingController();
  final _formKey = GlobalKey<FormState>();
  ValueChanged<String>? onChanged;
  bool _showIcons = false;
  bool _startValidateFPass = false;
  @override
  void initState() 
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Padding(
      padding: const EdgeInsets.only(bottom: 25.0),
      child: Wrap(
        children: [
          Container(
            child: Row(
              children: [
                Text("Password :"),
                TextButton(
                  onPressed: () 
                    _showDialog(context);
                  ,
                  child: Wrap(
                    direction: Axis.vertical,
                    alignment: WrapAlignment.end,
                    children: [Text("Change")],
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    );
  

  _showDialog(BuildContext context) async 
    var size = MediaQuery.of(context).size;
    return await showDialog(
        context: context,
        builder: (BuildContext context) 
          return AlertDialog(
            content: Stack(
              clipBehavior: Clip.none,
              children: <Widget>[
                Form(
                  key: _formKey,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: TextFormField(
                          controller: _fPasswordValue,
                          onChanged: (value) _onChange(_fPasswordValue.text);,
                          decoration: InputDecoration(
                            labelText: "New Password",
                            suffixIcon: _showIcons && _startValidateFPass ?  _setIcon() :null,
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: TextFormField(
                          controller: _sPasswordValue,
                          decoration: InputDecoration(
                            labelText: "Confirm Password",
                            suffixIcon: _showIcons && _startValidateFPass ?  _setIcon() :null, // I will change to check aothers soon 
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Wrap(
                          children: [
                            OutlinedButton(
                              style: OutlinedButton.styleFrom(
                                fixedSize: Size(size.width / 2 - 10, 20),
                                padding: EdgeInsets.symmetric(horizontal: 50),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(20)),
                              ),
                              onPressed: () ,
                              child: Text("CANCEL",
                                  style: TextStyle(
                                      fontSize: 14,
                                      letterSpacing: 2.2,
                                      color: Colors.black)),
                            ),
                            OutlinedButton(
                              style: OutlinedButton.styleFrom(
                                fixedSize: Size(size.width / 2 - 10, 20),
                                backgroundColor: Colors.blue[400],
                                primary: Colors.black,
                                padding: EdgeInsets.symmetric(horizontal: 50),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(20)),
                              ),
                              onPressed: () ,
                              child: Text("Save",
                                  style: TextStyle(
                                      fontSize: 14,
                                      letterSpacing: 2.2,
                                      color: Colors.black)),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          );
        );
  

  _onChange(String value) 
    setState(() 
      _startValidateFPass = true;
      if (value.length >= 8) 
        _sPasswordValue.text = "test"; // test to check setState
        _showIcons = true;
      
    );
  
  Icon _setIcon() 
    Icon icon;
    if(_showIcons)
      _sPasswordValue.text = "test"; // test to check setState
      print('dfsdfsd');
      icon = Icon(
        Icons.done_all,
        color: Colors.green,
      );
    else
      icon = Icon(
        Icons.highlight_off,
        color: Colors.red,
      );
    
    return icon;
  

【问题讨论】:

【参考方案1】:

制作另一个有状态小部件并将 Alertdialog 作为其子级或使用有状态构建器来完成此操作

    showDialog(
  context: context,
  builder: (context) 
    String contentText = "Your Dialog";
    return StatefulBuilder(
      builder: (context, setState) 
        return AlertDialog(
          title: Text("Title"),
          content: Text(contentText),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text("Cancel"),
            ),
            TextButton(
              onPressed: () 
                setState(() 
                  contentText = "Changed state";
                );
              ,
              child: Text("Change"),
            ),
          ],
        );
      ,
    );
  ,
);

【讨论】:

我已经创建了一个单独的 Stateful Widget,测试我的代码,你会看到有什么不同。 在有状态的小部件中有状态并将其传递给对话框的构建器,该对话框将像魅力一样工作

以上是关于Setstate() 无法更新 AlertDialog 中的 suffixIcon ? - 颤振的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS:警告:setState(...):在现有状态转换期间无法更新

为啥即使在有状态小部件中使用 setstate 也无法获取更新的变量。因为我想在新的 TabBar 选项上更新我的 Container

ref和setState合用时,怎样解决dom无法及时更新:setState是一个异步函数,但是提供了第二个参数,当dom更新完后后执行第二个参数里的内容

React setState注意事项

React-无法读取未定义的属性“setState”

setState 没有更新 React 中的设置值 [重复]