如何与具有textfield(autofocused为true)的键盘一起移动底页?

Man*_*Rao 8 dart flutter flutter-layout

我正在尝试制作一个具有文本字段的底表,并将自动对焦设置为true,以便弹出键盘。但是,底页与键盘重叠。有没有办法将底页移动到键盘上方?

Padding(
  padding:
      EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  child: Column(children: <Widget>[
    TextField(
      autofocus: true,
      decoration: InputDecoration(hintText: 'Title'),
    ),
    TextField(
      decoration: InputDecoration(hintText: 'Details!'),
      keyboardType: TextInputType.multiline,
      maxLines: 4,
    ),
    TextField(
      decoration: InputDecoration(hintText: 'Additional details!'),
      keyboardType: TextInputType.multiline,
      maxLines: 4,
    ),]);
Run Code Online (Sandbox Code Playgroud)

cap*_*apu 102

只需添加:

  • isScrollControlled: true 显示ModalBottomSheet
  • padding: MediaQuery.of(context).viewInsets 在构建器中小部件
  • 列/包装两个作品
showModalBottomSheet<void>(
  isScrollControlled: true,
  context: context,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.only(
        topLeft: Radius.circular(30.0),
        topRight: Radius.circular(30.0)),
  ),
  builder: (BuildContext context) {
    return Padding(
        padding: MediaQuery.of(context).viewInsets,
        child: Container(
            child: Wrap(
          children: <Widget>[
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            )
          ],
        )));
  },
);
Run Code Online (Sandbox Code Playgroud)

2020 年 2 月 25 日更新更好的解决方案

showModalBottomSheet(
 isScrollControlled: true,
 builder: (BuildContext context) {

    return SingleChildScrollView(
      child: Container(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: Padding(
          padding: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0), // content padding
          child: Form(...)) // From with TextField inside


});
Run Code Online (Sandbox Code Playgroud)

  • 请注意每个人:对于所提出的问题,不需要 Wrap 小部件,因为问题是bottomSheet 能够在键盘上方移动,而不是底部工作表本身的内容。 (2认同)

Ras*_*han 24

包: https: //pub.dev/packages/modal_bottom_sheet

将你的小部件包裹到 Padding 中并像这样设置 padding ==>

padding: MediaQuery.of(context).viewInsets // viewInsets will decorate your screen
Run Code Online (Sandbox Code Playgroud)

您可以使用 showMaterialModalBottomSheet 或 showModalBottomSheet 或 showCupertinoModalBottomSheet

showModalBottomSheet(
        context: context,
        barrierColor: popupBackground,
        isScrollControlled: true, // only work on showModalBottomSheet function
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(borderRadiusMedium),
                topRight: Radius.circular(borderRadiusMedium))),
        builder: (context) =>  Padding(
            padding: MediaQuery.of(context).viewInsets,
            child: Container(
                   height: 400, //height or you can use Get.width-100 to set height
                   child: <Your Widget here>
             ),)),)
Run Code Online (Sandbox Code Playgroud)

前

后


Rob*_*bin 18

在最新版本的 flutter 中,您可以使用isScrollControlledproperty/named 参数移动您的 bottomSheet 。假设我有一个函数(_showModal),它会在按下按钮时调用。我在该功能上定义了底部工作表功能。

void _showModal() {
  showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    builder: (BuildContext context) {
      return Column(
        children: <Widget>[
          TextField(// your other code),
          SizedBox(height: 5.0),
          TextField(// your other code),
          SizedBox(height: 5.0),
          TextField(// your other code),
        ]
      );
    },
  );
}
Run Code Online (Sandbox Code Playgroud)

这里会出现一个 ModalBottomSheet,但高度全屏。而且你不需要那个高度。所以,你需要 Column's mainAxisSizeto min.

Column(
  mainAxisSize: MainAxisSize.min,
  // your other code
)
Run Code Online (Sandbox Code Playgroud)

解决了全屏高度问题,但是出现键盘时ModalBottomSheet没有移动到顶部。好的,要解决此问题,您需要为viewInsetsModalBottomSheet设置底部填充。因此,要设置填充,我们需要用 Container 或 Padding 包裹我们的 Column,然后设置填充。最终代码将如下所示

void _showModal() {
  showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    builder: (BuildContext context) {
      return Container(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
        ),
        // You can wrap this Column with Padding of 8.0 for better design
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            TextField(// your other code),
            SizedBox(height: 5.0),
            TextField(// your other code),
            SizedBox(height: 5.0),
            TextField(// your other code),
          ]
        ),
      );
    },
  );
}
Run Code Online (Sandbox Code Playgroud)

希望你的问题得到解决。谢谢

  • 像魅力一样工作......! (2认同)

Zon*_*hao 13

对于那些尝试所有答案都无法解决问题的人。这些答案是正确的,但不太清楚。

使用时

MediaQuery.of(context).viewInsets.bottom)

确保您的上下文变量使用底部工作表构建器属性提供的变量。

builder :(**c**)=>MediaQuery.of(**c**)


Abe*_*bed 11

在flutter 1.7.X及更高版本中, 添加了更多功能,BottomSheetDialog因此除了@ anmol.majhail答案外,您还可以添加isScrollControlled = true其功能showModalBottomSheet,使底页能够占据所需的全部高度,从而提供了更多TextField未被键盘覆盖的保险。

像这样:

 showModalBottomSheet(
    shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
    backgroundColor: Colors.black,
    context: context,
    isScrollControlled: true,
    builder: (context) => Padding(
      padding: const EdgeInsets.symmetric(horizontal:18 ),
      child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12.0),
                child: Text('Enter your address',
                    style: TextStyles.textBody2),
              ),
              SizedBox(
                height: 8.0,
              ),
              Padding(
                padding: EdgeInsets.only(
                    bottom: MediaQuery.of(context).viewInsets.bottom),
                child: TextField(
                  decoration: InputDecoration(
                    hintText: 'adddrss'
                  ),
                  autofocus: true,
                  controller: _newMediaLinkAddressController,
                ),
              ),

              SizedBox(height: 10),
            ],
          ),
    ));
Run Code Online (Sandbox Code Playgroud)

请注意:

shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
Run Code Online (Sandbox Code Playgroud)

不是必需的 只是我正在创建一个圆形的底页。

更新资料

如果你的BottomSheetModel就是Column确保你添加 mainAxisSize: MainAxisSize.min,,否则这个表将覆盖整个屏幕。

  • 2021 年!你现在不需要它: `padding: MediaQuery.of(context).viewInsets` (4认同)
  • @Abed我尝试了你的方法。它不适用于我的问题吗..请检查/sf/ask/4076841471/ (3认同)
  • 应用此后,底部的工作表占据了整个屏幕。通过为底部工作表的容器小部件的高度属性放置一个静态值来解决这个问题。 (2认同)
  • 当输入聚焦在可滚动模式中时如何添加自动滚动? (2认同)

Nil*_*hod 9

尝试这个

我的解决方案是

  • isScrollControlled: true
  • 添加填充
    padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
    
    Run Code Online (Sandbox Code Playgroud)
  • 包裹你的布局 SingleChildScrollView

示例代码

Future<void> future = showModalBottomSheet(
  context: context,
  isDismissible: true,
  isScrollControlled: true,
  backgroundColor: Colors.white.withOpacity(0.2),
  builder: (context) => SingleChildScrollView(
    child: GestureDetector(
      child: Padding(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom
        ),
        child: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Column(
            children: <Widget>[
              // add your widget here
            ],
          ),
        ),
      )
    ),
  )
);
Run Code Online (Sandbox Code Playgroud)

  • SingleChildScrollView 包装的要点很重要。谢谢 (2认同)

小智 8

我通过在键盘打开时增加子小部件的高度来修复它。MediaQuery.of(context).viewInsets.bottom 的初始值将是 0 它会在键盘获得焦点时发生变化。

showModalBottomSheet<void>(
      enableDrag: true,
      isScrollControlled: true,
      context: context,
      builder: (BuildContext context) {
        return Card(
          color: Colors.white,
          child: Container(
            height: MediaQuery.of(context).size.height / 2 +
                MediaQuery.of(context).viewInsets.bottom,
            child: Column(
              children: <Widget>[
                TextField(),
                TextField(),
              ],
            ),
          ),
        );
      },
    );
Run Code Online (Sandbox Code Playgroud)


Akb*_*tov 8

2020 年更新!

这个答案是正确的,但您现在不必提供底部填充!找到并删除这一行:

padding: MediaQuery.of(context).viewInsets

**更新 2021 年 5 月 flutter 2.2!” 现在你需要给底部填充。上面写的是bug。

  • 谢谢你,好提示。您的解决方案对我有用(Flutter 稳定版本 60bd88df91)。但请查看 https://github.com/flutter/flutter/commits/master/packages/flutter/lib/src/material/bottom_sheet 上的 ref a5262(恢复“[showModalBottomSheet] 修复:showModalBottomSheet 不会沿键盘移动”)。镖。所以我认为我们可能需要在 Flutter 即将发布的更新中跟​​踪问题。 (2认同)

anm*_*ail 7

为了专注于键盘输入 BottomSheet- TextField在填充小部件中包裹,如下所示,例如代码:

showModalBottomSheet(
              context: context,
              builder: (context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.only(
                        bottom: MediaQuery.of(context).viewInsets.bottom),
                    child: TextField(
                      autofocus: true,
                    ),
                  ),
                );
              }); 
Run Code Online (Sandbox Code Playgroud)


小智 7

将其添加到底部工作表的最后一个小部件之后

Padding(padding: EdgeInsets.only(bottom:MediaQuery.of(context).viewInsets.bottom))
Run Code Online (Sandbox Code Playgroud)


Bor*_*tou 6

尝试这个。

showModalBottomSheet(
        isScrollControlled: true,
        context: context,
        builder: (context) {
          return AnimatedPadding(
              padding: MediaQuery.of(context).viewInsets,
              duration: const Duration(milliseconds: 100),
              curve: Curves.decelerate,
              child: Container(
                  child: Wrap(
                children: [
                  TextField(
                    decoration: InputDecoration(labelText: "1"),
                  ),
                  TextField(
                    decoration: InputDecoration(labelText: "2"),
                  ),
                  TextField(
                    decoration: InputDecoration(labelText: "3"),
                  ),
                ],
              )));
        },
      )
Run Code Online (Sandbox Code Playgroud)


小智 6

那么你应该使用这个,

showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    shape: RoundedRectangleBorder(
      // <-- for border radius
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(10.0),
        topRight: Radius.circular(10.0),
      ),
    ),
    builder: (BuildContext context) {
      return SingleChildScrollView(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: drunkenWidget()...

//BTW, Never ever Drink
Run Code Online (Sandbox Code Playgroud)


A J*_*A J 6

showModalBottomSheet(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(15.0),
      ),
      context: context,
      isScrollControlled: true,
      builder: (builder) {
        return Container(
          height: MediaQuery.of(context).size.height - 40,
          padding: MediaQuery.of(context).viewInsets,
          child: <Your Widget Here>,
        );
      },
    );
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述