Flutter Web中AlertDialog内TextFormField计数文本不更新问题排查
AlertDialog中TextFormField的counterText不更新问题解决
问题原因
你页面里的setState()只能刷新当前页面的组件,但AlertDialog是通过showDialog创建的独立弹窗路由,它的组件树和页面完全分离,所以页面的setState无法触发弹窗内部组件的重建,导致counterText不会跟着更新。
解决方案
方案1:用StatefulBuilder包裹弹窗内容
在AlertDialog的content中使用StatefulBuilder,这样就能在弹窗内部触发局部刷新:
showMyDialog() async { return showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { int dialogTextLength = 0; return AlertDialog( title: const Text( 'Share your thoughts!', style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, ), ), content: StatefulBuilder( builder: (context, setState) { return SizedBox( child: TextFormField( decoration: InputDecoration( contentPadding: const EdgeInsets.all(15), counterText: "$dialogTextLength", ), maxLength: maxLength, onChanged: (value) { controller.text = value; dialogTextLength = value.length; print("text length: $dialogTextLength"); print("controller text length: ${controller.text.length}"); // 调用StatefulBuilder的setState刷新弹窗内组件 setState(() {}); }, ), ); }, ), ); }, ); }
方案2:把弹窗抽成独立的StatefulWidget
如果弹窗逻辑复杂,单独封装成StatefulWidget会更清晰:
class MyInputDialog extends StatefulWidget { final TextEditingController controller; final int maxLength; const MyInputDialog({super.key, required this.controller, required this.maxLength}); @override State<MyInputDialog> createState() => _MyInputDialogState(); } class _MyInputDialogState extends State<MyInputDialog> { int textLength = 0; @override Widget build(BuildContext context) { return AlertDialog( title: const Text( 'Share your thoughts!', style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, ), ), content: TextFormField( decoration: InputDecoration( contentPadding: const EdgeInsets.all(15), counterText: "$textLength", ), maxLength: widget.maxLength, controller: widget.controller, onChanged: (value) { textLength = value.length; print("text length: $textLength"); print("controller text length: ${widget.controller.text.length}"); setState(() {}); }, ), ); } }
调用弹窗:
showMyDialog() async { return showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return MyInputDialog(controller: controller, maxLength: maxLength); }, ); }
额外优化:用TextFormField自带的计数功能
其实TextFormField本身就支持长度计数,不需要自己维护textLength,可以直接自定义计数样式:
TextFormField( maxLength: maxLength, decoration: InputDecoration( contentPadding: const EdgeInsets.all(15), counterText: "", // 关闭默认计数器样式 buildCounter: (context, {required currentLength, required isFocused, maxLength}) { return Text("$currentLength/$maxLength"); // 自定义计数文本 }, ), controller: controller, )
内容的提问来源于stack exchange,提问作者Arnob
相关产品推荐
相关产品推荐

