键盘出现时,Flutter小部件会调整大小.怎么预防这个?

Mar*_*ary 33 keyboard resize widget textfield flutter

我有一个这样的Expanded小部件列:

 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,
          ),
        ],
      ),
    );
Run Code Online (Sandbox Code Playgroud)

它看起来像这样: 在此输入图像描述

convertFrom,包括TextField.当我点击此文本字段时,Android键盘将出现在屏幕上.这会更改屏幕大小,因此小部件会像这样调整大小: 在此输入图像描述

有没有办法让键盘"覆盖"屏幕,以便我的列不调整大小?如果我不使用Expanded小部件并为每个小部件硬编码高度,则小部件不会调整大小,但是当键盘出现时(因为没有足够的空间),我会收到黑黄条纹错误.对于所有屏幕尺寸,这也不灵活.

我不确定这是特定于Android还是特定于Flutter.

azi*_*iza 116

在你的Scaffold,设置resizeToAvoidBottomInset属性为false.

  • 有没有办法产生类似于`android:windowSoftInputMode ="adjustPan"的效果?如果我将`resizeToAvoidBottomPadding`添加到脚手架,它最终会覆盖TextField. (4认同)
  • `resizeToAvoidBottomPadding` 已弃用,请使用 `resizeToAvoidBottomInset` [检查此答案](/sf/answers/3926670541/) (4认同)
  • 我不了解 android,但在这种情况下,将布局包装在 ListView 中通常是一个好习惯 (3认同)
  • 这与问题中建议的类型没有任何作用。键盘下方的所有小部件仍会调整大小。 (2认同)

Dun*_*nes 58

大多数其他答案建议使用resizeToAvoidBottomPadding=false. 根据我的经验,如果文本字段位于键盘出现的位置下方,则这允许键盘覆盖文本字段。

我目前的解决方案是强制我的列与屏幕高度相同,然后将其放置在 a 中,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
            ],
          ),
        ),
      ),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

我使用NeverScrollableScrollPhysics这样用户就不能自己滚动。

  • 我尝试了没有“NeverScrollableScrollPhysics”的方法,一切看起来都很好,除了用户可以尝试上下滑动并且他们可以看到过度滚动发光。当我使用 `NeverScrollableScrollPhysics` 时,它给我提供与 `resizeToAvoidBottomInset` 相同的行为 (6认同)
  • 但使用“NeverScrollableScrollPhysics”可以使其不会通过键盘向上滚动。 (6认同)
  • 删除 SingleChildScrollView Widget 的 NeverScrollableScrollPhysics() 行,或将 ClampingScrollPhysics() 替换到那里。然后它会随着键盘向上滚动。 (2认同)
  • 无论有或没有 IntrinsicHeight 小部件,我都有相同的行为。文档说要避免使用它:“这个类相对昂贵。尽可能避免使用它。” (2认同)

Den*_*Den 13

我的方法是SingleChildScrollViewClampingScrollPhysics物理学一起使用。

SingleChildScrollView(
  physics: ClampingScrollPhysics(),
  child: Container(),
)
Run Code Online (Sandbox Code Playgroud)


Pha*_*van 10

可能来不及回答了,但以下内容对我有用

Scaffold(
  body: SingleChildScrollView(
    physics: ClampingScrollPhysics(parent: NeverScrollableScrollPhysics()),
      child: Container(
Run Code Online (Sandbox Code Playgroud)

Clamping 将自动滚动以使文本字段可见,其父级 NeverScrollable 将不允许用户滚动。


Yau*_*nka 7

特征

  • 打开键盘时背景图像不会调整大小
  • 能够滚动隐藏在键盘后面的元素
import 'package:flutter/material.dart';

SizedBox addPaddingWhenKeyboardAppears() {
  final viewInsets = EdgeInsets.fromWindowPadding(
    WidgetsBinding.instance!.window.viewInsets,
    WidgetsBinding.instance!.window.devicePixelRatio,
  );

  final bottomOffset = viewInsets.bottom;
  const hiddenKeyboard = 0.0; // Always 0 if keyboard is not opened
  final isNeedPadding = bottomOffset != hiddenKeyboard;

  return SizedBox(height: isNeedPadding ? bottomOffset : hiddenKeyboard);
}

/// The size of the screen.
class ScreenSizeService {
  final BuildContext context;

  const ScreenSizeService(
    this.context,
  );

  Size get size => MediaQuery.of(context).size;
  double get height => size.height;
  double get width => size.width;
}

class LoginPage extends StatelessWidget {
  final _imageUrl =
      'https://images.unsplash.com/photo-1631823460501-e0c045fa716f?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyNHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60';

  const LoginPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final screenWidth = ScreenSizeService(context).width;
    final screenHeight = ScreenSizeService(context).height;

    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: NetworkImage(_imageUrl),
            fit: BoxFit.cover,
          ),
        ),
        child: SingleChildScrollView(
          child: ConstrainedBox(
            constraints: BoxConstraints(
              minWidth: screenWidth,
              minHeight: screenHeight,
            ),
            child: Column(
              children: [
                ...List.generate(6, (index) {
                  return Column(
                    children: [
                      Container(
                        height: 60,
                        width: double.maxFinite,
                        color: Colors.pink[100],
                        child: Center(child: Text('$index')),
                      ),
                      const SizedBox(height: 40),
                    ],
                  );
                }),
                Container(color: Colors.white, child: const TextField()),
                addPaddingWhenKeyboardAppears(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Art*_*mLK 6

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

    return Scaffold(
      resizeToAvoidBottomInset : false,
      body: YourWidgets(),
    );
Run Code Online (Sandbox Code Playgroud)

  • 它们是相同的答案@Ojonugwa,也许编辑在我发布我的答案后更新了接受的答案,所以现在的区别是我的包含了一个例子? (3认同)

Ton*_*oni 6

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()
        ],
      ),
    ),
  ),
);
Run Code Online (Sandbox Code Playgroud)


小智 6

false设置的值resizeToAvoidBottomInset对我来说效果很好。

另外,resizeToAvoidBottomPadding对我来说效果很好。您可以使用其中任何一个。

  • 如果你提到它的去向会更有用 (3认同)

小智 5

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

Scaffold(
      resizeToAvoidBottomPadding: false,
      appBar: AppBar()
)
Run Code Online (Sandbox Code Playgroud)

方法 2(不推荐):只需android:windowSoftInputMode="stateVisible"在活动中添加android AndroidManifest.xml 它将只适用于 Android 而不适用于 IOS 之类的。

<activity
       ...
        android:windowSoftInputMode="stateVisible">
Run Code Online (Sandbox Code Playgroud)

注意:不要设置为android:windowSoftInputMode="adjustResize"


SaM*_*MiX 5

避免调整小部件大小专注于文本字段的最佳解决方案是SingleChildScrollView()ClampingScrollPhysics()物理一起使用。另外,请记住为其子项设置高度(例如: use ),以便您可以通过以下方式使用您的小部件:container()Column()

return Scaffold(
   body: SingleChildScrollView(
      physics: ClampingScrollPhysics(),
      child: Container(
         height: size.height,
         child: Column(
            children:[
               TextFormField()
            ],
         ),
      ),
   ),
);
Run Code Online (Sandbox Code Playgroud)