在颤动中单击 TextFormField 后键盘正在关闭

Posted

技术标签:

【中文标题】在颤动中单击 TextFormField 后键盘正在关闭【英文标题】:Keyboard is closing after clicking on TextFormField in flutter 【发布时间】:2021-06-11 09:46:03 【问题描述】:

我在***上尝试了所有可能的答案,仍然无法解决这个问题。 每当我单击任何 TextFormField 时,它都会立即打开和关闭键盘。并且键盘尝试也涵盖了密码字段。

import 'package:flutter/material.dart';
import 'package:metro_prototype/pages/loginPage.dart';

import '../uiConstsants.dart';

class RegisterPage extends StatefulWidget 
  static final String routeName = "/registerPage";

  @override
  _RegisterPageState createState() => _RegisterPageState();


class _RegisterPageState extends State<RegisterPage> 
  @override
  Widget build(BuildContext context) 
    var width = MediaQuery.of(context).size.width;

    FocusScope.of(context).unfocus();
    return Scaffold(
      body: GestureDetector(
        onTap: () => FocusScope.of(context).unfocus(),
        child: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [Colors.white, color1])),
          //#002D72
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Hero(
                tag: 'logo',
                child: Padding(
                  padding:
                      const EdgeInsets.only(left: 100, right: 100, bottom: 30),
                  child: ClipOval(
                    child: Image.asset(
                      'images/haiko1.jpg',
                      height: width / 4,
                      width: width / 4,
                    ),
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(20.0),
                child: Container(
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(15)),
                  child: Padding(
                    padding: const EdgeInsets.all(25.0),
                    child: Column(
                      children: [
                        TextFormField(
                          decoration: textfield1Deco.copyWith(
                            prefixIcon: Icon(Icons.account_circle),
                            hintText: "Enter your name",
                            labelText: "Name",
                          ),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: textfield1Deco.copyWith(
                              prefixIcon: Icon(Icons.phone),
                              hintText: "Enter your mobile number",
                              labelText: "Mobile Number"),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: textfield1Deco.copyWith(
                            prefixIcon: Icon(Icons.lock),
                            hintText: "Enter your password",
                            labelText: "Password",
                          ),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: textfield1Deco.copyWith(
                            prefixIcon: Icon(Icons.lock),
                            hintText: "Enter your password",
                            labelText: "Password",
                          ),
                        ),
                        SizedBox(height: 30),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            getButton("Register", Icons.person_add, () 
                              Navigator.pop(
                                  context,
                                  PageRouteBuilder(
                                    transitionDuration:
                                        Duration(milliseconds: 2000),
                                    pageBuilder: (_, __, ___) => LoginPage(),
                                  ));
                            )
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  

我在列上遇到了渲染问题,我也尝试将它放在 SingleChildScrollView 中。

在布局期间抛出了以下断言:A RenderFlex 底部溢出 22 个像素。

相关的导致错误的小部件是:列 file:///D:/android/FlutterApp/metro_prototype/lib/pages/registerPage.dart:29:18 溢出的 RenderFlex 具有 Axis.vertical 的方向。这 溢出的 RenderFlex 边缘已在 用黄色和黑色条纹图案渲染。这通常是 由于内容对于 RenderFlex 来说太大。

考虑应用弹性因子(例如,使用扩展小部件) 强制 RenderFlex 的子级适应可用空间 而不是按照自然大小调整大小。这被认为是 错误条件,因为它表明有内容不能 可见。如果内容合法地大于可用的 空间,请考虑在放置之前使用 ClipRect 小部件对其进行裁剪 在 flex 中,或者使用可滚动容器而不是 Flex,例如 一个列表视图。

具体的 RenderFlex 是:RenderFlex#ee67d relayoutBoundary=up4 OVERFLOWING ... 需要合成 ... parentData:(可以使用大小)...约束: BoxConstraints(0.0

【问题讨论】:

你为什么把FocusScope.of(context).unfocus();放在构建中,在小部件之前? @AbdelrahmanSherif 如果我单击屏幕上的任意位置,则从 TextFormFields 中移除焦点。谢谢这有点解决了我的问题。 FocusScope.of(context).unfocus(); 的功能是什么? 好吧,试着删除它,看看结果如何。 @basudevnayak 它使键盘失焦,我把它放在了错误的位置。现在键盘问题消失了。即使我专注于任何 TextFormField,我也不知道 build 会被调用 【参考方案1】:

您的代码中有两个问题需要解决。

    键盘出现后立即消失。

这是因为在你的 Widget 构建函数中你有一个 FocusScope.of(context).unfocus();线。每次键盘出现时,都会重新构建屏幕布局,但在您的情况下,一旦构建完成,您也会移除焦点,因此键盘会返回。我不知道你为什么有那条线,但如果你把它去掉,键盘就会出现并停留。如果出于某种原因必须有该行(即,在第一次构建小部件时,必须移除焦点),则仅将其放在 initState 函数中,而不是在构建函数中。

    RenderFlex 溢出。

发生这种情况是因为您正在使用一个列,该列通常用于应该完全适合屏幕的布局。在您的情况下,当键盘出现时,屏幕上无法显示所有内容。如果您从顶部删除您的徽标,则有足够的空间,错误就会消失。您有另一个选择(如果您想保留徽标)是用 ListView 替换 Column。

这是对我有用的最终代码:

import 'package:flutter/material.dart';
import 'package:metro_prototype/pages/loginPage.dart';
import '../uiConstsants.dart';

class RegisterPage extends StatefulWidget 
  static final String routeName = "/registerPage";

  @override
  _RegisterPageState createState() => _RegisterPageState();


class _RegisterPageState extends State<RegisterPage> 

  @override
  void initState() 
    super.initState();
    FocusScope.of(context).unfocus();
  

  @override
  Widget build(BuildContext context) 
    var width = MediaQuery.of(context).size.width;

    // FocusScope.of(context).unfocus();
    return Scaffold(
      resizeToAvoidBottomInset: true,
      body: GestureDetector(
        onTap: () => FocusScope.of(context).unfocus(),
        child: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [Colors.white, color1])),
          //#002D72
          child: ListView(
            // mainAxisAlignment: MainAxisAlignment.center,
            // crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Hero(
                tag: 'logo',
                child: Padding(
                  padding:
                      const EdgeInsets.only(left: 100, right: 100, bottom: 30),
                  child: ClipOval(
                    child: Image.asset(
                      'images/haiko1.jpg',
                      height: width / 4,
                      width: width / 4,
                    ),
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(20.0),
                child: Container(
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(15)),
                  child: Padding(
                    padding: const EdgeInsets.all(25.0),
                    child: Column(
                      children: [
                        TextFormField(
                          decoration: InputDecoration(
                            prefixIcon: Icon(Icons.account_circle),
                            hintText: "Enter your name",
                            labelText: "Name",
                          ),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: InputDecoration(
                              prefixIcon: Icon(Icons.phone),
                              hintText: "Enter your mobile number",
                              labelText: "Mobile Number"),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: InputDecoration(
                            prefixIcon: Icon(Icons.lock),
                            hintText: "Enter your password",
                            labelText: "Password",
                          ),
                        ),
                        SizedBox(height: 30),
                        TextFormField(
                          decoration: InputDecoration(
                            prefixIcon: Icon(Icons.lock),
                            hintText: "Enter your password",
                            labelText: "Password",
                          ),
                        ),
                        SizedBox(height: 30),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            getButton("Register", Icons.person_add, () 
                              Navigator.pop(
                                  context,
                                  PageRouteBuilder(
                                    transitionDuration:
                                        Duration(milliseconds: 2000),
                                    pageBuilder: (_, __, ___) => LoginPage(),
                                  ));
                            )
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  

【讨论】:

【参考方案2】:

最好的解决方案是将 Column Widget 替换为 ListView Widget

【讨论】:

以上是关于在颤动中单击 TextFormField 后键盘正在关闭的主要内容,如果未能解决你的问题,请参考以下文章

如何在颤动中禁用 texformfield 输入?

在颤动中从 TextFormField 添加多个值

TextFormField 上的可点击图标 - 禁用 TextFormField 对图标单击的关注(颤振)

如何从颤动的表单中获取值?

如何在颤动中将焦点转移到下一个文本字段?

如果在颤动中获取某个日期,则禁用按钮