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

使用TextEditingController更新TextField值时出现异常求助

Flutter TextField光标跳回开头问题解决

问题根源

你遇到的输入时光标跳回开头的问题,核心原因有两个:

  1. 每次build都新建TextEditingController:在build方法里直接创建TextEditingController(text: inspectionTypeDis),组件每次重建都会生成新的控制器,输入状态被重置,光标自然跳回开头。
  2. build方法内修改状态触发重复重建:在build里直接给inspectionTypeDis赋值,会触发组件重新build,进一步导致控制器反复初始化。

修复方案

步骤1:将TextEditingController声明为State成员

在_EditCertificateInspection类里声明控制器,避免每次build都新建:

class _EditCertificateInspection extends State<EditCertificateInspection> {
  final navigatorKey = GlobalKey<NavigatorState>();
  final _formKey = GlobalKey<FormState>();
  // 声明控制器
  late TextEditingController _inspectionTypeController;

  @override
  void initState() {
    super.initState();
    // 初始化控制器
    _inspectionTypeController = TextEditingController();
  }

  @override
  void dispose() {
    // 销毁控制器,避免内存泄漏
    _inspectionTypeController.dispose();
    super.dispose();
  }
}

步骤2:在didChangeDependencies中更新控制器值

用didChangeDependencies生命周期方法替代build里的赋值操作,从Provider获取数据后更新控制器:

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  final certificatesData = Provider.of<Certificates>(context);
  final cerData = certificatesData.certData;
  if (cerData != null) {
    final inspectionType = cerData['inspectionType'];
    // 只有当值不同时才更新,避免不必要的刷新
    if (_inspectionTypeController.text != inspectionType) {
      _inspectionTypeController.text = inspectionType;
    }
    _clientDataL = clientDis;
    if (_clientDataL != null) {
      getClientEmailL(_clientDataL);
    }
  }
  if (emailClientDataL != null) {
    _emailClientDataL = clientEmailDis;
  }
}

步骤3:修改TextField使用控制器

去掉build里的临时控制器,直接使用成员变量,onChanged里可以直接通过控制器获取值:

subtitle: TextField(
  controller: _inspectionTypeController,
  onChanged: (text) {
    // 这里可以直接用_inspectionTypeController.text获取最新值,或者更新你的状态
    inspectionTypeDis = text;
  },
  decoration: const InputDecoration(
    border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
  ),
),

完整修改后的代码

class EditCertificateInspection extends StatefulWidget with InputValidationMixin {
  EditCertificateInspection({Key? key}) : super(key: key);
  @override
  _EditCertificateInspection createState() => _EditCertificateInspection();
}

class InputValidationMixin {}

class _EditCertificateInspection extends State<EditCertificateInspection> {
  final navigatorKey = GlobalKey<NavigatorState>();
  final _formKey = GlobalKey<FormState>();
  late TextEditingController _inspectionTypeController;

  // 假设这些是你已有的状态变量
  String? inspectionTypeDis;
  dynamic _clientDataL;
  dynamic clientDis;
  dynamic emailClientDataL;
  dynamic _emailClientDataL;
  dynamic clientEmailDis;

  void getClientEmailL(dynamic data) {
    // 你的方法实现
  }

  @override
  void initState() {
    super.initState();
    _inspectionTypeController = TextEditingController();
  }

  @override
  void dispose() {
    _inspectionTypeController.dispose();
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final certificatesData = Provider.of<Certificates>(context);
    final cerData = certificatesData.certData;
    if (cerData != null) {
      print("test in");
      inspectionTypeDis = cerData['inspectionType'];
      // 仅当值变化时更新控制器
      if (_inspectionTypeController.text != inspectionTypeDis) {
        _inspectionTypeController.text = inspectionTypeDis!;
      }
      _clientDataL = clientDis;
      if (_clientDataL != null) {
        getClientEmailL(_clientDataL);
      }
    }
    if (emailClientDataL != null) {
      _emailClientDataL = clientEmailDis;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: AlertDialog(
        title: Container(
          color: const Color.fromARGB(255, 75, 185, 159),
          padding: const EdgeInsets.all(17),
          margin: const EdgeInsets.all(0),
          child: const Text(
            'Edit',
            textAlign: TextAlign.center,
            style: TextStyle(color: Color.fromARGB(255, 250, 251, 250)),
          ),
        ),
        content: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              SizedBox(
                width: 630,
                height: 100,
                child: ListView(
                  shrinkWrap: true,
                  scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    Container(
                      width: 310,
                      height: 20,
                      child: ListTile(
                        title: const Text('Inspection Type'),
                        subtitle: TextField(
                          controller: _inspectionTypeController,
                          onChanged: (text) {
                            inspectionTypeDis = text;
                          },
                          decoration: const InputDecoration(
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(4)),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

关键说明

  • 把控制器声明为State成员,确保其生命周期与组件一致,避免重复创建。
  • 使用didChangeDependencies处理Provider数据更新,避免在build里修改状态导致无限重建。
  • 更新控制器时判断值是否变化,减少不必要的UI刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:35:26