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

Flutter TextFormField清空内容后失焦问题求助

问题分析与修复方案

核心问题1:Controller重复创建触发组件重建

在Consumer的builder方法中,你每次都会新建MaskedTextController并直接赋值文本,这会导致状态更新时CustomTextFormField频繁重建,直接丢失焦点。

核心问题2:自定义FocusScope干扰焦点管理

你手动给TextFormField套了一层自定义的FocusScopeNode,这会打乱默认的焦点流转逻辑,清空文本时的焦点请求会被这个自定义FocusScope拦截。


修复步骤

1. 重构Controller的创建与更新逻辑

把控制器的创建移到builder外部,用组件状态或状态管理工具保存实例,只在值真正变化时更新文本:

// 示例:在State类中管理控制器
class _YourFormState extends State<YourFormWidget> {
  late MaskedTextController cedulaController;

  @override
  void initState() {
    super.initState();
    cedulaController = MaskedTextController(mask: '000-0000000-0');
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final formValue = context.watch<YourFormValue>();
    // 仅当值不同时更新,避免不必要的组件重建
    if (cedulaController.text != formValue.cedula.value) {
      cedulaController.text = formValue.cedula.value;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      child: Column(
        children: [
          Consumer(
            builder: (context, watch, _) {
              return CustomTextFormField(
                readOnly: false,
                label: 'Digite su número de cédula',
                controller: cedulaController,
                onChanged: (cedula) async {
                  // 你的业务逻辑
                },
              );
            },
          ),
        ],
      ),
    );
  }
}

2. 移除多余的FocusScope配置

删除自定义的FocusScope包裹,让TextFormField使用默认的焦点管理体系:

// 修改后的CustomTextFormField核心代码
return TextFormField(
  focusNode: focusNode,
  textCapitalization: textCapitalization,
  onTapOutside: (event) => FocusScope.of(context).unfocus(),
  onChanged: (value) {
    onChanged?.call(value);
    // 用PostFrameCallback确保焦点请求在组件更新后执行
    if (value.isEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        focusNode?.requestFocus();
      });
    }
  },
  // 其他原有属性
);

3. 规范FocusNode的生命周期管理

如果focusNode是组件内部创建的,要在dispose方法中释放资源;如果是外部传入,避免在组件内销毁:

// 示例:在CustomTextFormField的State中管理FocusNode
class _CustomTextFormFieldState extends State<CustomTextFormField> {
  late FocusNode _focusNode;

  @override
  void initState() {
    super.initState();
    _focusNode = widget.focusNode ?? FocusNode();
  }

  @override
  void dispose() {
    // 仅销毁组件内部创建的FocusNode
    if (widget.focusNode == null) {
      _focusNode.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      focusNode: _focusNode,
      // 其他属性
    );
  }
}

内容的提问来源于stack exchange,提问作者Rickard245

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:30:10