我有一个像这样的扩展小部件列:

 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 widgets,并为每个widget硬编码一个高度,这些widget就不会调整大小,但是当键盘出现时,我会得到一个黑黄条纹错误(因为没有足够的空间)。这也不是对所有屏幕尺寸都灵活。

我不确定这是android特有的还是flutter特有的。


更新后的答案

resizeToAvoidBottomPadding现在已弃用。

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


原来的答案

在你的Scaffold中,设置resizeToAvoidBottomPadding属性为false。


根据用例,您还可以考虑使用列表视图。这将确保当没有足够的空间时,内容会滚动。作为一个例子,你可以在图库应用程序中查看文本框演示


将resizeToAvoidBottomInset设置为false,而不是已弃用的resizeToAvoidBottomPadding。

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

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

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

方法2(不推荐):只需添加android:windowSoftInputMode=" statevvisible "在android AndroidManifest.xml的活动,它将只适用于android和不适用于IOS像。

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

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


大多数其他答案建议使用resizeToAvoidBottomPadding=false。根据我的经验,这允许键盘掩盖文本字段,如果它们在键盘出现的地方下面。

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

Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      physics: const 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,这样用户就不能自己滚动了。


好吧,我认为如果我们实现@Aman的解决方案,它将使我们的应用程序行为丑陋,因为当键盘出现时,它不会调整我们的屏幕视口根据可用的高度,它将使其他字段隐藏在键盘后面。所以我建议用esinglechildscrollview代替。

包装您的代码与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与ClampingScrollPhysics物理。

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

对我来说,下面的项目属性从真变为假

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

在文件

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

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


我的建议是使用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()
        ],
      ),
    ),
  ),
);

我也面临着同样的问题,我开始尝试随机的解决方案来解决它,突然它就解决了。

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

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


避免调整小部件大小并同时关注文本字段的最佳解决方案是使用SingleChildScrollView()和ClampingScrollPhysics()物理。另外,记得为它的子元素设置高度(例如:use container()),这样你就可以通过Column()来使用你的小部件:

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

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

此外,resizeToAvoidBottomPadding对我来说工作得很好。你可以用任何一个。


这是一个完美的解决方案,使您能够在SingleChildScrollView中拥有一个全屏列。这可以让你为所有屏幕大小创建一个完美的布局+有一个可滚动的屏幕,只有当你打开键盘或屏幕在呈现后溢出时才滚动(例如文本输入字段验证)

class PerfectFullScreen extends StatelessWidget {
  const PerfectFullScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      appBar: AppBar(),
      body: Builder(
        builder: (context) => SingleChildScrollView(
            child: ConstrainedBox(
                constraints: BoxConstraints(
                    minHeight: MediaQuery.of(context).size.height -
                        (MediaQuery.of(context).padding.top + kToolbarHeight)),
                child: IntrinsicHeight(
                    child: Column(
                  children: [
                    Container(
                      height: randomImageHeight,
                      child: Image.asset(
                        "assets/images/change_password.png",
                        fit: BoxFit.cover,
                      ),
                    ),
                    Expanded(
                        child: WidgetThatShouldTakeRemainingSpace() )
                  ],
                )))),
      ),
    ));
  }
}

重要的部分是带有正确BoxConstraints和InstrinsicHeight小部件的ConstrainedBox。

PS: MediaQuery.of .padding(上下文)。top + kToolbarHeight) == Appbar的高度


现在回答可能太迟了,但下面的方法对我有用

Scaffold(
  body: SingleChildScrollView(
    physics: ClampingScrollPhysics(parent: NeverScrollableScrollPhysics()),
      child: Container(

夹紧将自动滚动使文本字段可见,它的父NeverScrollable将不允许用户滚动。


特点:

打开键盘时,背景图像不会调整大小 能够滚动隐藏在键盘后面的元素

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(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

这将滚动您的键盘和崩溃大小时,键盘消失。

showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      builder: (context) {
        return Padding(
            padding: MediaQuery.of(context).viewInsets,
            child:SingleChildScrollView(
            physics: ClampingScrollPhysics(),
            child: Container(.......)));

当我们点击文本框和键盘打开媒体查询时,这种奇怪的媒体查询行为在堆栈中重建了一个相同的页面。

MaterialApp ( useInheritedMediaQuery:真的,)

useInheritedMediaQuery设为true会有帮助。


我有同样的问题与我的屏幕,这里我如何解决它:

Scaffold(
  resizeToAvoidBottomInset: false, 
  ... 
)


你可以使用

Scaffold(
  resizeToAvoidBottomInset: false, 
  ... 
)

或者可以将小部件打包

SingleChildScrollView