如何将底页与具有文本字段的键盘一起移动(自动对焦为真)?
Posted
技术标签:
【中文标题】如何将底页与具有文本字段的键盘一起移动(自动对焦为真)?【英文标题】:How to Move bottomsheet along with keyboard which has textfield(autofocused is true)? 【发布时间】:2019-05-20 23:58:26 【问题描述】:我正在尝试制作一个包含文本字段且自动对焦设置为 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,
),]);
【问题讨论】:
Github 上还有一些未解决的问题:main issue 和 another 带有提供动画解决方案的评论。 对我来说,只需添加一个Padding
元素作为Column
的最后一个子元素并将其填充设置为padding: MediaQuery.of(context).viewInsets
即可解决此问题
【参考方案1】:
将isScrollControlled = true
添加到BottomSheetDialog
它将允许底部表格占据所需的全部高度,从而更加确保TextField
不会被键盘覆盖。
使用MediaQuery.of(context).viewInsets.bottom
添加键盘填充
注意
如果您的BottomSheetModel
是Column
,请确保添加mainAxisSize: MainAxisSize.min,
,否则表格将覆盖整个屏幕。
示例
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))),
这不是必需的。只是我正在创建一个圆形底片。
padding: MediaQuery.of(context).viewInsets
更新 Flutter 2.2 再次打破了这些变化!”现在您需要再次提供底部填充,这样键盘就不会与底部表重叠。
【讨论】:
应用后,底部的工作表占据了整个屏幕。通过为底部工作表的 Container 小部件的 height 属性放置一个静态值来解决它。 @Abed 我试过你的方法。它对我的问题不起作用吗..请检查***.com/q/58240592/8822337 2021 年!你现在不需要它:padding: MediaQuery.of(context).viewInsets
在 showModalBottomSheet 上添加“isScrollControlled = true”,在 Column 小部件上添加“mainAxisSize: MainAxisSize.min”解决了我的所有问题。谢谢阿贝德。
当输入聚焦在可滚动模式中时如何添加自动滚动?【参考方案2】:
只需添加:
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'),
)
],
)));
,
);
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
);
【讨论】:
只是给每个人的提示:对于所提出的问题,不需要 Wrap 小部件,因为问题在于 bottomSheet 能够在键盘上方移动,而不是其自身的底部工作表的内容。 它对我有用【参考方案3】:为了专注于BottomSheet
中的键盘 - 将TextField
包裹在 Padding 小部件中,如下所示,例如代码:
showModalBottomSheet(
context: context,
builder: (context)
return Container(
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: TextField(
autofocus: true,
),
),
);
);
【讨论】:
您好,谢谢。这适用于两个子字段,但在我们添加第三个字段时无效。我用我的代码示例编辑了问题。 @ManjunathRao 您可能需要在文本字段中添加“密钥”以保持它们的唯一性,以便获得超过 2 个。如果这有帮助,请告诉我BottomSheet
- 具有maxHeight: constraints
,因为字段正在增加,高度不会增加。您可以在 BottomSheet 中使用 ListView
使字段在滚动中可见。或者你可以试试这个 - ***.com/questions/53311553/…
@ManjunathRao - 你不会在 BottomSheet 中获得两个以上的字段 - 由于maxHeight: constraints
【参考方案4】:
在最新版本的颤振中,您可以使用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),
]
);
,
);
这里会出现一个 ModalBottomSheet,但高度全屏。而且你不需要那个高度。所以,你需要将Column的mainAxisSize
改为min
。
Column(
mainAxisSize: MainAxisSize.min,
// your other code
)
解决了全屏高度问题,但出现键盘时 ModalBottomSheet 不会移到顶部。好的,要解决此问题,您需要将 viewInsets
底部填充设置为您的 ModalBottomSheet。所以要设置填充,我们需要用 Container 或 Padding 包裹我们的列,然后设置填充。最终代码如下所示
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),
]
),
);
,
);
希望您的问题得到解决。谢谢?
【讨论】:
像魅力一样工作......!?【参考方案5】:试试这个
我的解决方案是
使用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
],
),
),
)
),
)
);
【讨论】:
SingleChildScrollView 的包装点很重要。谢谢【参考方案6】:我通过在打开键盘时增加子小部件的高度来修复它。 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(),
],
),
),
);
,
);
【讨论】:
【参考方案7】:包裹:https://pub.dev/packages/modal_bottom_sheet
将您的小部件包装到 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>
),)),)
【讨论】:
【参考方案8】:2021 年 5 月更新 2.2! 现在你需要给底部填充。下面写的是一个错误。
2020 年更新!
这个answer 是真的,但你现在不必给底部填充! 查找并删除此行:
padding: MediaQuery.of(context).viewInsets
【讨论】:
谢谢,好提示。您的解决方案对我有用(Flutter 稳定版 60bd88df91)。但是在github.com/flutter/flutter/commits/master/packages/flutter/lib/… 处查看参考 a5262(还原“[showModalBottomSheet] 修复:showModalBottomSheet 不会沿键盘移动”)。所以我认为我们可能需要在即将到来的 Flutter 更新中跟踪问题。 已确认,flutter 2.2 再次打破了这一点,您再次需要 MediaQuery。【参考方案9】:如果您有全屏或固定尺寸showModalBottomSheet
,请不要使用padding
,它不会解决您的问题。像这样使用margin
而不是padding
:
showModalBottomSheet(
context: context,
builder: (context)
return Container(
marign: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: TextField()
);
);
【讨论】:
【参考方案10】:对于那些尝试所有答案都无法解决问题的人。这些答案是正确的,但不是很清楚。
使用时
MediaQuery.of(context).viewInsets.bottom)
builder :(**c**)=>MediaQuery.of(**c**)
【讨论】:
【参考方案11】:结合不同的解决方案后,我得到了这个:
如果您不希望它是 全屏 并且不想使用 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(Channel master,v1.15.3-pre.37,Mac OS X 10.15.2 19C57,语言环境 en-US)
【讨论】:
【参考方案12】:不要在构建器中使用builder: (BuildContext context)
,而是使用builder: (context)
使用此解决方案,我的模态底部工作表会粘在状态栏上(类似于 Scaffold
和 resizeToAvoidBottomInset: false
),并允许查看所有表单字段并在仍需要查看底部文本字段时滚动表单。
有关更多详细信息,这是我找到解决方案的链接-https://github.com/flutter/flutter/issues/18564#issuecomment-602604778
【讨论】:
【参考方案13】:在github找到这个
Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: TextField()
)
【讨论】:
【参考方案14】:试试这个。
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"),
),
],
)));
,
)
【讨论】:
【参考方案15】:用Scaffold
小部件包裹Form
,然后用SingleChildScrollView
包裹TextFormField
:
return Container(
height: screenHeight * .66,
child: Scaffold(
body: Form(
key: _form,
child: SingleChildScrollView(
child:TextFormField()
)
)
)
)
【讨论】:
Scaffold(child:
?【参考方案16】:
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()));
注意:这条线可以发挥所有作用
【讨论】:
【参考方案17】:然后你被命令使用这个,
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
【讨论】:
【参考方案18】:在底部表格的最后一个小部件之后添加它
Padding(padding: EdgeInsets.only(bottom:MediaQuery.of(context).viewInsets.bottom))
【讨论】:
【参考方案19】:简单的解决方案,您可以自定义:
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",
)),
),
【讨论】:
【参考方案20】:只需添加
if (_isEditing) SizedBox(height: MediaQuery.of(context).viewInsets.bottom),
在键盘下方并用
隐藏文本字段下方的所有其他内容if (!_isEditing) Widget(...),
【讨论】:
以上是关于如何将底页与具有文本字段的键盘一起移动(自动对焦为真)?的主要内容,如果未能解决你的问题,请参考以下文章