如何将底页与具有文本字段的键盘一起移动(自动聚焦为真)?

我正在尝试制作一个有文本字段的底页,并将自动对焦设置为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,
),]);
107132 次浏览

为了关注BottomSheet中的键盘-在填充小工具中包装TextField,如下所示,例如代码:

showModalBottomSheet(
context: context,
builder: (context) {
return Container(
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: TextField(
autofocus: true,
),
),
);
});
  • 要解决此问题
  1. isScrollControlled = true添加到BottomSheetDialog,它将允许底部薄片获得所需的全部高度,这为键盘不覆盖TextField提供了更多保障。

  2. 使用MediaQuery.of(context).viewInsets.bottom

    添加键盘填充

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

  2. 使用多个TextField或TextFormField

  • 例子
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
backgroundColor: Colors.black,
context: context,
isScrollControlled: true,
builder: (context) => Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
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,
),
TextField(
decoration: InputDecoration(
hintText: 'adddrss'
),
autofocus: true,
controller: _newMediaLinkAddressController,
),
                  



SizedBox(height: 10),
],
),
));

请注意:

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

这不是必须的。只是我在做一个圆形的底页。

  • 已更新

Flutter 2.2再次中断更改!现在您需要再次提供底部填充,以便键盘不会与底部重叠。

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


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

只需添加:

  • isScrollControlled: true到ShowModalBottomSheet
  • 将ABC0__到生成器中的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'),
)
],
)));
},
);

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




});

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

如果您不希望它是全屏,并且不希望使用填充,解决方法是使用

  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(Channel Master,v1.15.3-pre.37,适用于Mac OS X 10.15.2 19C57,区域设置为en-US)

试试这个

我的解决方案是

  • 使用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
],
),
),
)
),
)
);

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

如果你有全屏或固定大小的showModalBottomSheet,不要使用padding,它不会解决你的问题。使用margin代替padding,如下所示:

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

在最新版本的Flutter中,您可以使用isScrollControlled属性/命名参数来移动您的底表。假设我有一个函数(_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),
]
);
},
);
}

这里将出现一个模态底表,但高度为全屏。你不需要那么高。因此,您需要将列的mainAxisSize转换为min

Column(
mainAxisSize: MainAxisSize.min,
// your other code
)

全屏的高度问题解决了,但是出现键盘时,ModalBottomSheet不会移到顶部。好的,要解决这个问题,您需要将viewInsets底部填充设置为您的ModalBottomSheet.因此,要设置填充,我们需要用容器或填充来包装我们的列,然后设置填充。最终的代码如下所示

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

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

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

注意:这条线发挥了所有的魔力。

不要在生成器中使用builder: (BuildContext context) { },而应使用builder: (context) { }

有了这个解决方案,我的模态底表就会粘在状态栏上(就像ScaffoldresizeToAvoidBottomInset: false),并允许查看所有表单字段,如果仍然需要查看底部文本字段,还可以滚动表单。

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

GitHub上找到这个

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

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

使用时

MediaQuery.of(context).viewInsets.bottom)

确保上下文变量使用的是Bottom Sheet Builder属性提供的变量。

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

更新2021年5月颤音2.2! 现在你需要给底部填充。下面写的是一个错误。

2020年更新!

这个回答是正确的,但你现在不必给出底部填充! 查找并删除此行:

padding: MediaQuery.of(context).viewInsets

试试这个。

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

那你应该用这个,

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

简单的解决方案,您可以自定义:

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",
)),
),

只需添加

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

并隐藏TextField下面的所有其他内容。

if (!_isEditing) Widget(...),

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

将小部件包装到填充中,并像这样设置填充==>;

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

将此添加到底页的最后一个小部件之后

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

如果您仍未找到您的问题。所以我认为你错过了你的BuilderContext。有时,当您实现ModalBottomSheet时,它将只提供上下文参数。因此,使用BuildContext添加上下文。

 builder: (BuildContext context) {  //-Here is your issue add BuilderContext class name as it as
return Padding(
padding: MediaQuery.of(context).viewInsets,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: new Container(
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>,
);
},
);

enter image description here

import 'dart:async';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import '../weight/boostrap/flutter_bootstrap.dart';
import '../weight/boostrap/bootstrap_widgets.dart';


/*
TextEditingController txtname = TextEditingController();
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
builder: (context) => SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom),
child: new AddItem(
tektk: 'Category',
tektd: 'Add',
txtname: txtname,
ismultik:false,
onPressed: () {}),
),
);
*/
class AddItem extends StatelessWidget {
const AddItem(
{Key? key,
required this.ismultik,
required this.tektd,
required this.tektk,
required this.txtname,
required this.onPressed})
: super(key: key);
final bool ismultik;
final String tektk;
final String tektd;
final VoidCallback? onPressed;
final TextEditingController txtname;
@override
Widget build(BuildContext context) {
final MediaQueryData mediaQueryData = MediaQuery.of(context);
bootstrapGridParameters(gutterSize: 10);
return Padding(
padding: mediaQueryData.viewInsets,
child: Container(
padding: EdgeInsets.only(bottom: 90.0, left: 10.0, right: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ListTile(
trailing: SizedBox.fromSize(
size: Size(35, 35),
child: ClipOval(
child: Material(
color: Colors.indigo,
child: InkWell(
splashColor: Colors.white,
onTap: () {
Navigator.pop(context);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.close, color: Colors.white),
],
),
),
),
),
),
),
BootstrapRow(height: 0, children: [
BootstrapCol(
sizes: 'col-md-12',
child: TextField(
style: TextStyle(color: Colors.black),
decoration: new InputDecoration(
border: new OutlineInputBorder(
borderSide: new BorderSide(color: Colors.white)),
labelText: tektk,
),
keyboardType: ismultik == true
? TextInputType.multiline
: TextInputType.text,
maxLines: null,
minLines: 1,
controller: txtname,
),
),
BootstrapCol(
sizes: 'col-md-12',
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green, // background
onPrimary: Colors.white, // foreground
),
onPressed: onPressed,
child: Text(tektd)),
),
]),
],
),
),
);
}
}

将此添加到您的路由器链接模式底页中

 showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return Messagescr();
}
);

在你的脚手架上也要拆除这条线:

resizeToAvoidBottomInset : false,