当键盘出现时,Flutter小部件将调整大小。如何预防呢?


114

我有一列展开式小部件,如下所示:

 return new Container(
      child: new Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          new Expanded(
            flex: 1,
            child: convertFrom,
          ),
          new Expanded(
            flex: 1,
            child: convertTo,
          ),
          new Expanded(
            flex: 1,
            child: description,
          ),
        ],
      ),
    );

看起来像这样:

在此处输入图片说明

convertFrom,包括一个TextField。当我点击此文本字段时,Android键盘将出现在屏幕上。这会更改屏幕大小,因此小部件的大小将如下调整:

在此处输入图片说明

有没有一种方法可以让键盘“覆盖”屏幕,使我的专栏不改变大小?如果我不使用Expanded小部件,并且不对每个小部件的高度进行硬编码,则这些小部件不会调整大小,但是在键盘出现时会出现黑色和黄色的条纹错误(因为没有足够的空间)。这对于所有屏幕尺寸也不是很灵活。

我不确定这是Android专用还是Flutter专用。


在您的脚手架主体中使用SingleChildScrollView。
linhadiretalipe

Answers:


286

更新的答案

resizeToAvoidBottomPadding现在已弃用

更新的解决方案是将resizeToAvoidBottomInset属性设置为false


原始答案

在中Scaffold,将resizeToAvoidBottomPadding属性设置为false


11
有什么办法产生类似的效果android:windowSoftInputMode="adjustPan"吗?如果我添加resizeToAvoidBottomPadding到脚手架,它将最终覆盖TextField。
Epicality,2018年

3
我不了解android,但在这种情况下,将布局包装在ListView中通常是一个好习惯
aziza

@aziza,我遇到了同样的问题,但是在您的解决方案正常工作后,但是还有另一个问题,请检查链接中的视频当键盘出现时,图像闪烁。dropbox.com/s/lian92mnzz8kv9w/FlutterIssue1.mov?dl=0
Kishan Vyas

@KishanVyas与我相同的图像消失了。
stickedoverflow

@aziza可靠答案
Val

35

其他大多数答案建议使用resizeToAvoidBottomPadding=false。以我的经验,这允许键盘掩盖文本字段(如果它们位于出现键盘的位置下方)。

我当前的解决方案是强制将列的高度设置为与屏幕相同,然后将其放置在一个高度上,SingleChildScrollView以便Flutter在使用键盘时自动将屏幕向上滚动到足够的高度。

Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      physics: NeverScrollableScrollPhysics(),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: MediaQuery.of(context).size.width,
          minHeight: MediaQuery.of(context).size.height,
        ),
        child: IntrinsicHeight(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              // CONTENT HERE
            ],
          ),
        ),
      ),
    ),
  );
}

NeverScrollableScrollPhysics这样做是为了使用户无法在自己周围滚动。


4
我尝试了没有的方法NeverScrollableScrollPhysics,除了用户可以尝试上下滑动并且可以看到过度滚动的光辉之外,其他所有看起来都不错。当我使用NeverScrollableScrollPhysics它时,它的行为与resizeToAvoidBottomInset
Sajad Jaward

将主属性设置为false。
VLXU

1
但是使用NeverScrollableScrollPhysics可以使它也不会随键盘向上滚动。
hiwa doski

18

设置resizeToAvoidBottomInset为,false而不是resizeToAvoidBottomPadding不推荐使用。

    return Scaffold(
      resizeToAvoidBottomInset : false,
      body: YourWidgets(),
    );

3
它们是@Ojonugwa相同的答案,也许编辑者在我发布了我的答案后更新了可接受的答案,所以现在不同之处在于我的答案包含示例吗?
ArtiomLK

5

我的方法是SingleChildScrollViewClampingScrollPhysics物理学结合使用。

SingleChildScrollView(
  physics: ClampingScrollPhysics(),
  child: Container(),
)

4

方法1:android:windowSoftInputMode="adjustResize"从AndroidManifest.xml文件中删除(否则它将覆盖Flutter代码)并添加resizeToAvoidBottomPadding: false如下所示的Scaffold:

Scaffold(
      resizeToAvoidBottomPadding: false,
      appBar: AppBar()
)

方法2(不推荐):android:windowSoftInputMode="stateVisible"在活动中添加android AndroidManifest.xml,它将仅适用于Android,不适用于IOS。

<activity
       ...
        android:windowSoftInputMode="stateVisible">

注意:请勿将其设置为android:windowSoftInputMode="adjustResize"


4

好吧,我想如果我们实现@Aman的解决方案,它将使我们的应用程序在出现键盘时表现得很丑陋,不会根据可用高度调整屏幕的视口,并且会发现其他字段隐藏在键盘后面。所以我建议SingleChildScrollView改用。

使用SingleChildScrollView以下代码包装您的代码,

 return new Container(
  child: SingleChildScrollView(
    child: new Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[
      new Expanded(
        flex: 1,
        child: convertFrom,
      ),
      new Expanded(
        flex: 1,
        child: convertTo,
      ),
      new Expanded(
        flex: 1,
        child: description,
      ),
    ],
  ),
 ),
);

您知道以下事实,这将立即引发大量错误,因为扩展后的小部件将具有singlechildscrollview给定的无限填充空间
Christian X

2

根据用例,您还可以考虑使用listview。这样可以确保在没有足够空间的情况下滚动内容。例如,您可以在图库应用程序中查看文本字段演示


4
但这仍然不能使您选择的TextField可见,键盘仍会与之重叠。您必须自己滚动。不是用来作为一个Android开发者/用户
孩子

2

我的建议是,resizeToAvoidBottomInset: false如果键盘突然出现在屏幕上,则无论如何都要使用以防止小部件调整大小。例如,如果用户在您的应用程序中使用Facebook聊天头。

为了防止键盘覆盖小部件,建议在需要的屏幕上使用以下方法,即将高度SingleChildScrollView降低为可用空间的高度。在这种情况下,SingleChildScrollView还滚动到聚焦的窗口小部件。

final double screenHeight = MediaQuery.of(context).size.height;
final double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
return Scaffold(
  resizeToAvoidBottomInset: false,
  body: SizedBox(
    height: screenHeight - keyboardHeight,
    child: SingleChildScrollView(
      child: Column(
        children: [
          const SizedBox(height: 200),
          for (var i = 0; i < 10; i++) const TextField()
        ],
      ),
    ),
  ),
);

1

对我来说,将以下项目属性从true更改为false

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

在文件中

android/app/src/main/res/values/styles.xml

使Flutter在输入焦点上将所有页面内容向上拖动

颤动将所有页面内容在输入焦点上向上拖动


这将只适用于android系统...
Christian X

1

我遇到了同样的问题,因此我开始尝试随机解决方案来修复它,然后突然修复了它。 在此处输入图片说明

将主父容器包装在SingleChildScrollView()中,并为其指定设备高度,即device_height = MediaQuery.of(context).size.height。

这将使整个页面可滚动,但不会调整任何小部件的大小。


工作完美!谢谢!!
Gihan Sandaru

很高兴我能帮助你 !
Rudr Thakur
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.