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

Flutter技术求助:隐藏虚拟键盘后TextField值为空

问题原因与解决方案

嘿,这个问题的核心原因其实很明确——你把email和password这两个变量声明在了build方法内部!

为什么会出现这种奇怪的现象?

Flutter的build方法会在UI需要更新时重新执行,比如当你隐藏虚拟键盘时,屏幕的可用空间发生变化,会触发页面重绘,build方法就会重新跑一遍。这时候你在build里定义的String email = '';和String password = '';会被重新初始化为空字符串,所以点击按钮时自然打印不出内容。

而当虚拟键盘打开时,你输入完直接点击按钮,这时候页面还没触发重绘,变量还保留着你输入的值,所以能正常打印。


修复步骤

只需要把这两个变量移到_StudentLoginScreenState类的成员变量位置,让它们的生命周期和页面状态绑定,而不是每次build都重置:

class _StudentLoginScreenState extends State<StudentLoginScreen> {
  // 把变量移到类的成员区域,初始化一次即可
  String email = '';
  String password = '';

  @override
  Widget build(BuildContext context) {
    final AuthService _authService = AuthService();
    Size size = MediaQuery.of(context).size;
    // 删掉这里的变量声明!
    // String email = '';
    // String password = '';

    return Scaffold(
      // 后续代码保持不变,建议在onChanged里加上setState(好习惯)
      body: SafeArea(
        child: ListView(
          children: <Widget>[
            // ...
            RoundedInputField(
              hintText: "Email",
              onChanged: (val) { 
                setState(() { // 加上setState,确保状态变化被Flutter感知
                  email = val; 
                }); 
              },
            ),
            // ...
            RoundedInputField(
              hintText: "Password",
              boolean: true,
              onChanged: (val) { 
                setState(() {
                  password = val; 
                }); 
              },
            ),
            // ...
            FlatButton(
              onPressed: () async {
                print(email);
                print(password);
              },
              // ...
            ),
          ],
        ),
      ),
    );
  }
}

额外优化建议

如果你的表单逻辑后续会更复杂(比如表单验证、清空输入等),推荐使用TextEditingController来管理输入内容,这样操作会更灵活,还能避免一些状态同步问题:

class _StudentLoginScreenState extends State<StudentLoginScreen> {
  // 声明控制器
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  // 记得在页面销毁时释放控制器,防止内存泄漏
  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final AuthService _authService = AuthService();
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      backgroundColor: HexColor(studentPrimaryColour),
      body: SafeArea(
        child: ListView(
          children: <Widget>[
            // ...
            // 修改RoundedInputField,让它支持接收controller参数
            RoundedInputField(
              hintText: "Email",
              controller: _emailController, // 绑定控制器
            ),
            // ...
            RoundedInputField(
              hintText: "Password",
              boolean: true,
              controller: _passwordController,
            ),
            // ...
            FlatButton(
              onPressed: () async {
                // 通过controller获取输入值
                print(_emailController.text);
                print(_passwordController.text);
              },
              // ...
            ),
          ],
        ),
      ),
    );
  }
}

// 对应的RoundedInputField修改:
class RoundedInputField extends StatefulWidget {
  final String hintText;
  final ValueChanged<String> onChanged;
  final Color color;
  final bool boolean;
  final TextEditingController controller; // 添加controller参数

  RoundedInputField({ 
    Key key, 
    this.hintText, 
    this.onChanged, 
    this.color, 
    this.boolean = false, 
    this.controller, // 加入参数
  }) : super(key: key);

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

class _RoundedInputFieldState extends State<RoundedInputField> {
  @override
  Widget build(BuildContext context) {
    return TextFieldContainer(
      child: TextFormField(
        controller: widget.controller, // 绑定到TextFormField
        onChanged: widget.onChanged,
        obscureText: widget.boolean,
        decoration: InputDecoration(
          hintText: widget.hintText,
          border: InputBorder.none,
        ),
      ),
    );
  }
}

这样不管键盘隐藏与否,输入的值都能被正确保留和获取啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:47:37