You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:16:05