Flutter调用setState未更新AlertDialog内密码输入框可见性问题
问题原因
- 你当前调用的
setState是所属父页面的状态更新方法,而通过showGeneralDialog弹出的对话框是独立于父页面的新路由,父页面状态更新不会触发对话框内容重绘,只有重新打开对话框时才会加载最新的状态值。 - 代码还存在变量名混用问题:图标显隐判断用的是
passwordPortalVisible,但点击事件修改的是passwordVisible,两个变量不一致也会导致逻辑异常。
解决方案
核心是把对话框内容封装为独立的StatefulWidget,让对话框自己管理内部状态,点击切换可见性时调用对话框自身的setState就能实时刷新UI,修改后的可运行代码如下:
首先抽离独立的有状态密码对话框组件:
import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; // 独立的密码输入对话框组件,自身持有状态 class PasswordInputDialog extends StatefulWidget { // 传入需要的外部参数 final MaterialColor greyColor; final VoidCallback onConfirm; final TextEditingController textController; const PasswordInputDialog({ super.key, required this.greyColor, required this.onConfirm, required this.textController, }); @override State<PasswordInputDialog> createState() => _PasswordInputDialogState(); } class _PasswordInputDialogState extends State<PasswordInputDialog> { // 对话框内部管理密码可见性状态 bool _passwordVisible = false; @override Widget build(BuildContext context) { return AlertDialog( content: Wrap( alignment: WrapAlignment.center, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: TextField( decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10)), ), hintText: '请输入密码', suffixIconConstraints: const BoxConstraints.tightFor( height: 50, width: 50, ), suffixIcon: Padding( padding: const EdgeInsets.only(top: 5), child: SizedBox( width: 24, height: 24, child: IconButton( icon: _passwordVisible ? SvgPicture.asset( "assets/svgs/icons/visibility_off.svg", fit: BoxFit.scaleDown, color: widget.greyColor.shade400, ) : SvgPicture.asset( "assets/svgs/icons/visibility_on.svg", fit: BoxFit.scaleDown, color: widget.greyColor.shade400, ), onPressed: () { // 调用对话框自身的setState实时刷新UI setState(() { _passwordVisible = !_passwordVisible; }); }, ), ), ), ), controller: widget.textController, keyboardType: TextInputType.number, obscureText: !_passwordVisible, ), ), ], ), Padding( padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10), child: Row( children: [ Expanded( child: ElevatedButton( onPressed: widget.onConfirm, child: const Text('确定'), ), ), ], ), ), ], ), ); } }
然后修改原有的对话框调用逻辑:
getConfirmationPortalKey() { return showGeneralDialog( transitionBuilder: (ctx, anim1, anim2, child) => BackdropFilter( filter: ImageFilter.blur( sigmaX: 4 * anim1.value, sigmaY: 4 * anim1.value, ), child: FadeTransition( opacity: anim1, child: child, ), ), context: context, barrierDismissible: true, barrierLabel: '', barrierColor: Colors.black26, transitionDuration: const Duration(milliseconds: 200), pageBuilder: (ctx, anim1, anim2) => PasswordInputDialog( greyColor: widget.colors.grey, textController: textEditingControllerKey, onConfirm: () { UserLogin user = UserLogin(); // 此处补充确认按钮的其余逻辑 }, ), ); }
内容的提问来源于stack exchange,提问作者Kaya Ryuuna
相关产品推荐
相关产品推荐

