Flutter TextFormField被键盘遮挡

67

注意:我正在使用Navigator.of(context).push来推ModalRoute,

嗨,我有一个包含在主体中的TextFormFieldModalRoute页面,但是当键盘出现时,输入框被键盘遮挡了,如何解决?

enter image description here

return Container(
      child: ListView(
          children: <Widget>[
            //other widget
            SizedBox(height: _qtyAnimation.value),
            Row(
              children: <Widget>[
                Expanded(
                  child: Text(
                    "Jumlah",
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
                SizedBox(
                  width: 145.0,
                  child: TextFormField(
                    focusNode: _qtyFocusNode,
                    controller: qty,
                    keyboardType: TextInputType.number,
                    textAlign: TextAlign.center,
                    decoration: InputDecoration(
                      contentPadding: EdgeInsets.all(0.0),
                      prefixIcon: IconButton(
                        icon: Icon(Icons.remove),
                        onPressed: () {},
                      ),
                      border: OutlineInputBorder(
                        borderSide:
                            BorderSide(color: Colors.grey, width: 0.1),
                      ),
                      suffixIcon: IconButton(
                        icon: Icon(Icons.add),
                        onPressed: () {},
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ],
    );

这是我的代码,我尝试使用focusnode和其他方法,但结果仍然相同。 请帮帮我。


你可以使用FocusNode来实现这个功能:https://dev59.com/7FUL5IYBdhLWcg3wK1YU - Blasanka
可能是如何隐藏屏幕键盘?的重复问题。 - Blasanka
这对我没用,已经测试了那个链接。 - RIFAL
我的解决方案在这个帖子中链接。它非常简短和简单,不需要动画。 - Son Nguyen
14个回答

92
感谢您解决了我的文本框底部填充问题。
    Padding(
             padding: EdgeInsets.only(
             bottom: MediaQuery.of(context).viewInsets.bottom));

并倒置列表


很棒的解决方案! :) - madlick71
确实是个很棒的解决方案!谢谢。 - Rodolfo Gonçalves

68

这对我有效...

首先添加这个

final bottom = MediaQuery.of(context).viewInsets.bottom;

然后使用SingleChildScrollView()将主部件(无论您使用的是什么,例如Column,ListView等)包装起来,就像这样...

你需要 "reverse: true"

Widget build{
return Scaffold(
body: SingleChildScrollView(
reverse: true;
child: Container(...

对于 Scaffold,您也需要这两行代码。

return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(...

最后,参考“bottom”来设置您的EdgeInsets。

body: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Container(...

1
padding: EdgeInsets.only(bottom: bottom) 报错:bottom 必须是一个常量... 你该如何解决? - Fabio Magarelli
1
Fabio,请在Widget _body(WriteReviewModel model) {之后添加'final bottom = MediaQuery.of(context).viewInsets.bottom; - Haris
这是我在使用ConstrainedBox和SingleChildScrollView时,为了在列底部组合扩展的多行文本字段而找到的唯一有效方法。 - jeanadam
1
应用上述解决方案后:当TextFormField获得焦点时,它已经在键盘之上并向上移动,在屏幕上不可见。理想情况下,它应该保持在原地,只有屏幕下方的TextFormField应该向上滚动。 - Chinmay Mourya

20

您需要将所有内容包裹在SingleChildScrollView中,并将reverse设置为true。

SingleChildScrollView(
   reverse: true,
   child: Container(),
);

这对我很有效!


7
如果您的内容默认情况下不滚动(没有键盘弹出),这是最简单的解决方案。确实,如果您的内容大于屏幕高度,它将始终向底部滚动,即使没有键盘。这可能不是您想要的结果。 - Yann39

12
我有类似的问题。我尝试了所有的解决方案,但没有奏效。最终,我删除了

我有类似的问题。我尝试了所有的解决方案,但没有奏效。最终,我删除了

<item name="android:windowFullscreen">true</item>

从我的 Android 文件夹中的 styles.xml 文件中获取内容并修复问题。


对我来说,在调试版本中这个功能可以正常工作,但在发布版本中键盘只是弹出并立即隐藏,请确认是否有其他人也遇到了同样的问题? - Vamsi
1
没问题,它在debug和release模式下都能正常工作。 你必须有其他的配置引起了这个问题。尝试在一个干净的项目中进行测试。 - Guillermo De La Cruz

10

1
无法工作,我的文本字段位于行内和大小框中。 - RIFAL
1
https://www.didierboelens.com/2018/04/hint-4-ensure-a-textfield-or-textformfield-is-visible-in-the-viewport-when-has-the-focus/ - Blasanka

4

为了补充常见的答案,这是其余内容:

body: SingleChildScrollView(
          reverse: true,
          child: Container(
              child: Padding(
            padding: EdgeInsets.only(bottom: bottom),
            child: Stack(
              fit: StackFit.loose,
              children: <Widget>[

我在底部插入了一个东西,以防止其上升过高。

    var bottom = MediaQuery.of(context).viewInsets.bottom;
bottom = max(min(bottom, 80), 0);

4
我在 modal_bottom_sheet 插件中使用表单元素。 我通过将以下代码添加到 SingleChildScrollView 来解决它。
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)

这对我来说并没有改变问题。 - Petro

4

在你的Scaffold小部件内将resizeToAvoidBottomInset设置为false

请注意,resizeToAvoidBottomPadding将被废弃。

Scaffold( resizeToAvoidBottomInset: false, ...)

我花了太长时间才了解resizeToAvoidBottomInset。每次我使用弹性布局时,我的键盘都会出问题。这太糟糕了。 - Lewis

2

对我有效的做法是将这些提示与文档结合起来。它使用了LayoutBuilder、SingleChildScrollView、Padding(带底部hack)和最后是ConstrainedBox(用于使用Expanded)。通过组合它们,可以在列内使用扩展小部件。

文档(其中包括LayoutBuilder):https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

结构

 return Scaffold(
      resizeToAvoidBottomInset: false,
      resizeToAvoidBottomPadding: false,`

body: SafeArea(
        child: Container(
          child: LayoutBuilder(builder:
              (BuildContext context, BoxConstraints viewportConstraints) {
            return SingleChildScrollView(
              reverse: true,
              child: Padding(
                padding: EdgeInsets.only(bottom: bottom),
                child: ConstrainedBox(
                  constraints: BoxConstraints(
                      minHeight: viewportConstraints.maxHeight,
                      maxHeight: viewportConstraints.maxHeight),
                  child: Column(

这个案例在 beta 频道上对我来说直接就能运行。 - Nickolay Savchenko

1
为了使内容居中,首先在构建方法上添加以下代码:

...

final bottom = MediaQuery.of(context).viewInsets.bottom;

并返回这个:

return GestureDetector(
      onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        body: Stack(
          fit: StackFit.expand,
          children: [
            ///Content
            Align(
              alignment: Alignment.center,
              child: SingleChildScrollView(
                reverse: true,
                child: Padding(
                  padding: EdgeInsets.only(bottom: bottom),
                  child: Column(
                    children: [
                      MyContent()
                    ],
                  ),
                ),
              ),
            ),
            ///Button
            Align(
              alignment: Alignment.bottomCenter,
              child: MyBottomButton()
            )
          ],
        ),
      ),
    );

它与键盘流非常配合,效果非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接