You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter中点击TextField后组件重建致键盘闪退的问题求助

解决Flutter表单点击TextField键盘弹出后立即关闭、组件重建的问题

嘿,这个问题我之前开发表单时也踩过坑!核心原因很明确:你把表单的GlobalKey、TextEditingController这些需要持久化状态的变量都放在了build()方法内部——而Flutter的build()会在很多场景下被重新调用(比如键盘弹出、页面布局变化、调用setState()时),每次调用都会重新创建这些变量的新实例,导致TextField失去绑定的控制器,键盘直接关闭,整个表单组件也跟着重置了。

解决步骤

  1. _formKey、所有TextEditingController移到_UserLoaderState类的成员变量区域,脱离build()方法
  2. dispose()方法中销毁控制器,避免内存泄漏(规范操作)

修改后的完整代码示例

import 'package:flutter/material.dart'; 
import '../model/User.dart'; 
import './FileManager.dart'; 
import './MyListPage.dart'; 

class UserLoader extends StatefulWidget { 
  @override 
  _UserLoaderState createState() => new _UserLoaderState(); 
} 

class _UserLoaderState extends State<UserLoader> { 
  final userFileName = "user_infos.txt"; 
  User _user; 

  // --- 把状态变量移到类成员区域,确保生命周期内唯一 ---
  final _formKey = GlobalKey<FormState>();
  final _firstNameController = TextEditingController();
  final _lastNameController = TextEditingController();
  final _emailController = TextEditingController();
  final _phoneController = TextEditingController();

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

  @override 
  Widget build(BuildContext context) { 
    print("build UserLoader"); 

    // --- 这里不再重新定义状态变量 ---
    return new Scaffold( 
      appBar: new AppBar( 
        title: new Text("Informations"), 
        actions: <Widget>[ 
          new IconButton( 
            icon: const Icon(Icons.save), 
            onPressed: () { 
              _user = _onFormValidate( 
                _formKey.currentState, 
                _firstNameController.text, 
                _lastNameController.text, 
                _emailController.text, 
                _phoneController.text); 
            }) 
        ], 
      ), 
      body: new Center( 
        child: new SingleChildScrollView( 
          child: new Form( 
            key: _formKey, 
            child: new Column(children: <Widget>[ 
              new ListTile( 
                leading: const Icon(Icons.person), 
                title: new TextFormField( 
                  decoration: new InputDecoration( 
                    hintText: "Prénom", 
                  ), 
                  keyboardType: TextInputType.text, 
                  controller: _firstNameController, 
                  validator: _validateName, 
                ), 
              ), 
              new ListTile( 
                leading: const Icon(Icons.person), 
                title: new TextFormField( 
                  decoration: new InputDecoration( 
                    hintText: "Nom", 
                  ), 
                  keyboardType: TextInputType.text, 
                  controller: _lastNameController, 
                  validator: _validateName, 
                ), 
              ), 
              // 剩下的表单字段直接沿用即可...
            ]), 
          ), 
        ), 
      ), 
    ); 
  }

  // 补充你的验证和表单处理方法(示例)
  String? _validateName(String? value) {
    if (value == null || value.isEmpty) {
      return '请输入姓名';
    }
    return null;
  }

  User _onFormValidate(FormState? state, String firstName, String lastName, String email, String phone) {
    state?.save();
    return User(firstName: firstName, lastName: lastName, email: email, phone: phone);
  }
}

这样修改后,控制器和表单Key会在State实例的生命周期内保持唯一,不会因为build()重新执行而被重置,键盘弹出后就能正常保持打开状态,用户可以顺利完成表单填写了。

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

火山引擎 最新活动