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

时间:2018-12-20 12:48:50

标签: 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,
    ),]);

18 个答案:

答案 0 :(得分:13)

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

请注意:

shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),

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

更新

如果您的BottomSheetModelColumn,请确保添加mainAxisSize: MainAxisSize.min,,否则工作表将覆盖整个屏幕。

答案 1 :(得分:8)

2020 年更新!

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

padding: MediaQuery.of(context).viewInsets

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

答案 2 :(得分:8)

在最新版本的flutter中,您可以使用procedure TMyForm.cbb1Select(Sender: TObject); var Province: string; begin Province := cbb1.Items[cbb1.ItemIndex]; lst1.Clear; with dmAfritours do begin tblReserves.First; while not tblReserves.Eof do begin // alternatively, consider using the DataSet's Filter property instead... if tblReserves['Province'] = Province then begin lst1.Items.Add(tblReserves['ReserveName']); end; tblReserves.Next; end; end; end; 属性/命名参数移动bottomSheet。假设我有一个函数(_showModal),当按下按钮时会调用该函数。我在该功能上定义了底层功能。

isScrollControlled

此处将显示ModalBottomSheet,但具有全屏高度。而且您不需要那个高度。因此,您需要将Column的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), ] ); }, ); } mainAxisSize

min

全屏高度问题已解决,但出现键盘时ModalBottomSheet不会移到顶部。好的,要解决此问题,您需要将Column( mainAxisSize: MainAxisSize.min, // your other code ) 底部填充设置为ModalBottomSheet。因此,要设置填充,我们需要将“列”包装为“容器”或“填充”,然后设置填充。最终代码将如下所示:

viewInsets

希望您的问题已解决。谢谢?

答案 3 :(得分:7)

我通过在打开键盘时增加子窗口小部件的高度来解决此问题。 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(),
              ],
            ),
          ),
        );
      },
    );

答案 4 :(得分:4)

尝试一下

我的解决方案是

  • 使用isScrollControlled: true,
  • 添加填充padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom)
  • 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
                ],
              ),
            ),
          )),
        ));

答案 5 :(得分:2)

试试这个。

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

答案 6 :(得分:2)

结合不同的解决方案后,我得到了:

如果您不希望它成为全屏,并且不想使用 Padding 解决方法

  showModalBottomSheet(
      context: context,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      enableDrag: true,
      isDismissible: true,
      useRootNavigator: true,
      builder: (BuildContext ctx) {
        return Scaffold( // use CupertinoPageScaffold for iOS
          backgroundColor: Colors.transparent,
          resizeToAvoidBottomInset: true, // important
          body: SingleChildScrollView(
            child: Form(
              child: Container(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    TextFormField(),
                    TextFormField(),
                  ],
                ),
              ),
            ),
          ),
        );
      },
    );

Flutter(在Mac OS X 10.15.2 19C57上为Channel Master,v1.15.3-pre.37,语言环境为美国)

答案 7 :(得分:2)

如果您使用全屏或固定大小的showModalBottomSheet,请不要使用padding,这将无法解决您的问题。像这样使用margin代替padding

  showModalBottomSheet(
          context: context,
          builder: (context) {
            return Container(
                marign: EdgeInsets.only(
                    bottom: MediaQuery.of(context).viewInsets.bottom),
                child: TextField()
            );
          }); 

答案 8 :(得分:2)

为了专注于BottomSheet中的键盘-将Padding Widget中的TextField包裹起来,例如下面的代码:

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

答案 9 :(得分:2)

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

使用时

MediaQuery.of(context).viewInsets.bottom)

确保您的上下文变量正在使用底部工作表生成器属性提供的变量。

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

答案 10 :(得分:1)

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

    return SingleChildScrollView(
      child: Container(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: Padding(
          padding: const EdgeInsets.all(15.0), // content padding
          child: Container())});

注意:这行尽了所有的魔力

答案 11 :(得分:1)

使用builder: (BuildContext context) { }

代替在构建器中使用builder: (context) { }

使用此解决方案时,我的模式底部工作表会粘贴到状态栏上(与ScaffoldresizeToAvoidBottomInset: false一样工作),并允许查看所有表单字段并在仍然需要查看底部时滚动浏览表单文本字段。

有关更多详细信息,这是我找到解决方案的链接-https://github.com/flutter/flutter/issues/18564#issuecomment-602604778

答案 12 :(得分:1)

我的解决方法是:

  • isScrollControlled:是,
  • 填充:MediaQuery.of(context).viewInsets
  • 使用Wrap widget
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'),
            )
          ],
        )));
  },
);

答案 13 :(得分:0)

github上突出显示

Padding(
  padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  child: TextField()
)

答案 14 :(得分:0)

Form小部件包装Scaffold,然后用TextFormField包装SingleChildScrollView


 return Container(
          height: screenHeight * .66,
          child: Scaffold(
             body: Form(
               key: _form,
               child: SingleChildScrollView(
                 child:TextFormField()
               )
              )
             )
           )

答案 15 :(得分:0)

简单的解决方案,你可以自定义这个:

Container(
          margin: EdgeInsets.only(left: 15),
          child: InkWell(
              onTap: () {
                showModalBottomSheet(
                    isScrollControlled : true,
                    context: context,
                    backgroundColor: Colors.transparent,
                    builder: (context) {
                      return Container(
                        padding: EdgeInsets.only(top: 15, left: 15, right: 15, bottom: 10),
                        width: double.infinity,
                        decoration: BoxDecoration(
                          color: AppTheme.leadItemColor1,
                          borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
                        ),
                        child: Column(
                          children: [
                            _assignTo(widget.viewModel, context),
                            SizedBox(height: 12,),
                            txtComment(widget.viewModel),
                            SizedBox(height: 12,),
                            CRMButton(
                              title: 'Select',
                              onTap: () async {
                                Navigator.pop(context);
                                await widget.viewModel.updateStatus(7, why: "${ConstantData.lostOptions[_selectedNumber]}");
                              },
                            )
                          ],
                        ),
                      );
                    },
                );
              },
              child: CustomTabBarItem1(
                image: widget.viewModel.leadDetail.success.lStatus == 7 ? 'assets/appimages/LeadDetail/icons-03-01.png' : 'assets/appimages/LeadDetail/icons-04-01.png',
                bottomTitle: 'Lost',
                topTitle: widget.viewModel.leadDetail.success.lStatus > 7 ? 'assets/appimages/LeadDetail/Ellipse 61@2x.png' : widget.viewModel.leadDetail.success.lStatus == 7 ? 'assets/appimages/LeadDetail/Group 486-1.png' : 'assets/appimages/LeadDetail/Ellipse-61@3x.png',
                height : widget.viewModel.leadDetail.success.lStatus == 7 ? "0" : "1",
              )),
        ),

答案 16 :(得分:0)

只需添加

if (_isEditing) SizedBox(height: MediaQuery.of(context).viewInsets.bottom),

在键盘下并使用

隐藏文本字段下方的所有其他内容
if (!_isEditing) Widget(...),

答案 17 :(得分:0)

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

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

padding: MediaQuery.of(context).viewInsets // viewInsets will decorate your screen

你可以使用 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>
             ),)),)

before

after