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

Flutter切换TextField或改变状态时丢失输入状态的问题求助

问题:TextField切换焦点或关闭键盘时输入内容丢失

我有两个不同的TextField组件,切换焦点到另一个TextField,或者关闭键盘改变状态时,之前输入的内容会全部丢失,就像触发了setState()清除了所有页面数据。我确定是TextEditingController相关的问题,已经创建了两个独立的TextEditingController并传入对应的CustomTextInput组件,还为组件设置了唯一key,但问题依然存在,请问问题出在哪里?


相关代码

FormSection类

class FormSection extends StatelessWidget {
  final TextEditingController _mailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  FormSection({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CustomTextInput(
          placeholder: "E - Posta",
          controller: _mailController,
        ),
        const SizedBox(height: 10),
        CustomTextInput(
          placeholder: "Şifre",
          controller: _passwordController,
          isPassword: true,
        ),
        const SizedBox(height: 10),
        ButtonBar(
          children: [
            LoginPageButtons(
              buttonText: "Üye Ol",
              buttonFunction: () {},
            ),
            LoginPageButtons(
              buttonText: "Giriş Yap",
              buttonFunction: () {
                signInWithEmailAndPassword(
                    emailAddress: _mailController.text,
                    password: _passwordController.text);
              },
            ),
          ],
        ),
      ],
    );
  }
}

CustomTextInput类

class CustomTextInput extends StatefulWidget {
  final String placeholder;
  final TextEditingController controller;
  final bool? isPassword;

  CustomTextInput({
    Key? key,
    required this.placeholder,
    required this.controller,
    this.isPassword,
  }) : super(key: key);

  @override
  _CustomTextInputState createState() => _CustomTextInputState();
}

class _CustomTextInputState extends State<CustomTextInput> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(8.0),
      decoration: BoxDecoration(
        border: Border.all(
          color: MainTheme.secondaryColor, // Border color
          width: 2.0, // Border width
        ),
        borderRadius: BorderRadius.circular(10.0), // Border radius
      ),
      child: TextFormField(
        key: widget.key, // Unique key for each TextFormField
        obscureText: widget.isPassword ?? false,
        controller: widget.controller,
        style: MainTheme.themeData.textTheme.displaySmall!
            .copyWith(color: MainTheme.thirdColor),
        decoration: InputDecoration(
          hintStyle: MainTheme.themeData.textTheme.displaySmall!
              .copyWith(color: MainTheme.thirdColor),
          hintText: widget.placeholder, // Placeholder text
          border: InputBorder.none, // Remove the default underline border
        ),
      ),
    );
  }
}

问题根源与解决办法

问题核心在于FormSection是StatelessWidget,你把TextEditingController直接声明在了StatelessWidget的内部。当Widget树因键盘弹出/收起、焦点切换等场景重建时,StatelessWidget会被重新实例化,导致_mailController和_passwordController被重新初始化,之前存储的输入内容自然丢失。

修复步骤

  1. 将FormSection改为StatefulWidget,把TextEditingController移到对应的State类中,利用State的生命周期保存控制器实例
  2. 在State的dispose()方法中销毁控制器,避免内存泄漏

修改后的FormSection代码

class FormSection extends StatefulWidget {
  FormSection({super.key});

  @override
  State<FormSection> createState() => _FormSectionState();
}

class _FormSectionState extends State<FormSection> {
  late final TextEditingController _mailController;
  late final TextEditingController _passwordController;

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

  @override
  void dispose() {
    _mailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CustomTextInput(
          placeholder: "E - Posta",
          controller: _mailController,
        ),
        const SizedBox(height: 10),
        CustomTextInput(
          placeholder: "Şifre",
          controller: _passwordController,
          isPassword: true,
        ),
        const SizedBox(height: 10),
        ButtonBar(
          children: [
            LoginPageButtons(
              buttonText: "Üye Ol",
              buttonFunction: () {},
            ),
            LoginPageButtons(
              buttonText: "Giriş Yap",
              buttonFunction: () {
                signInWithEmailAndPassword(
                    emailAddress: _mailController.text,
                    password: _passwordController.text);
              },
            ),
          ],
        ),
      ],
    );
  }
}

另外,CustomTextInput中TextFormField的key: widget.key可以保留,但并非必要,因为控制器已经完成了输入框与数据的关联,不影响功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:22:50