如何使底栏随键盘向上移动(颤动)
Posted
技术标签:
【中文标题】如何使底栏随键盘向上移动(颤动)【英文标题】:How to make the bottom bar move up with the keyboard (flutter) 【发布时间】:2021-03-03 09:15:21 【问题描述】:我试图让我的聊天栏(文本字段、2 个按钮和文本字段后面的黑条)在使用时随键盘一起升起。
我尝试了以下方法:
使用底部的定位小部件中的所有元素包装堆栈:MediaQuery.of(context).viewInsets.bottom
,
但是,如果我这样做,它会摆脱 2 个按钮和黑条,并且在使用键盘时不会提升文本字段。
使用底部填充堆栈:MediaQuery.of(context).viewInsets.bottom
,
这会导致与上面 #1 中相同的不良结果
将堆栈包装在单个子滚动视图中: Move textfield up when keyboard appears in Flutter 如果我将堆栈包装在 singlechildscrollview 中,则在使用键盘时它不会移动。
如果有人能引导我朝着正确的方向前进,也许我将它们包装在错误的小部件中,或者我必须使用动画来向上移动堆栈。
代码如下:
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'main.dart';
import 'recurringwidgets/size_config.dart';
class ChatDemo extends StatefulWidget
ChatDemo();
@override
_ChatDemoState createState() => _ChatDemoState();
class _ChatDemoState extends State<ChatDemo> with RouteAware
double scrollMark;
@override
void initState()
void didChangeDependencies()
super.didChangeDependencies();
routeObserver.subscribe(this, ModalRoute.of(context));
@override
void dispose()
routeObserver.unsubscribe(this);
super.dispose();
@override
Widget build(BuildContext context)
return Scaffold(
backgroundColor: Colors.purple[300],
resizeToAvoidBottomInset: false,
//resizeToAvoidBottomPadding: true,
body: SafeArea(
bottom: false,
top: false,
child: //Column(
//mainAxisAlignment: MainAxisAlignment.spaceAround,
//children: <Widget>[
Stack(
children: <Widget>[
//header(context, "Chat"),
//EdgeInsets.fromLTRB(2.5, 184, 2.5, 126),
//padding: EdgeInsets.only(top:105),
GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Container(
),
),
Positioned(
child: Padding(
padding: EdgeInsets.only(top: 750 * SizeConfig.heightRatio, ),
child: SingleChildScrollView(
child: Stack(
children: [
Positioned(
top: 22.5 * SizeConfig.heightRatio,
bottom: 0,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32.0),
topRight: Radius.circular(32.0),
),
child: ClipRect(
//clipBehavior: Clip.antiAlias,
child: BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 20,
sigmaY: 20,
),
child: Transform.translate(
offset: Offset(0, 20 * SizeConfig.heightRatio),
child: Container(
constraints: BoxConstraints(
maxHeight: 75,
minHeight: 42,
), //height: 42,
width: SizeConfig.screenWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32.0),
topRight: Radius.circular(32.0),
),
color:
const Color(0xFF000000)//.withOpacity(0.00),
),
),
),
),
),
),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children:[
Padding(
padding: EdgeInsets.only(left:20.0,bottom: (10)),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(27.5),
boxShadow: [
BoxShadow(
color: const Color(0x29000000),
offset: Offset(3, 3),
blurRadius: 6,
),
],
),
child: CircleAvatar( ///radius 22
backgroundColor: Color(0xffffffff),
radius: 22,
child: SvgPicture.string(
_svg_nznkw8,
allowDrawingOutsideViewBox: true,
fit: BoxFit.fill,
),
),
),
),
Flexible(
flex:6,
child: Container(
),
),
Padding(
padding: const EdgeInsets.only(right:20.0,bottom: 10),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(27.5),
boxShadow: [
BoxShadow(
color: const Color(0x29000000),
offset: Offset(3, 3),
blurRadius: 6,
),
],
),
child: CircleAvatar( ///radius 22
backgroundColor:Color(0xffffffff) ,
radius: 22,
child: SvgPicture.string(
_svg_52blhh,
allowDrawingOutsideViewBox: true,
fit: BoxFit.fill,
),),
),
),
],
),
],
),
)
),
),
Padding(
padding: EdgeInsets.only(top:760*SizeConfig.heightRatio,left:60,),
child: Container(
//margin: EdgeInsets.only(top:760),
child: ChatBubble()),
),
],
),
),
);
class ChatBubble extends StatefulWidget
const ChatBubble(
Key key,
) : super(key: key);
@override
ChatBubbleState createState() => ChatBubbleState();
class ChatBubbleState extends State<ChatBubble>
@override
Widget build(BuildContext context)
final TextEditingController myController = TextEditingController();
//builds the bar
return Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Container(
//margin: EdgeInsets.only(top:13,bottom: 5),
//color: Colors.blue,
/*constraints: BoxConstraints(
maxHeight: 176,
),*/
//height: chatBarHeight,
constraints: BoxConstraints(
maxHeight: 176,
minHeight: 47.5, //52.5
),
width: 240.0 * SizeConfig.widthRatio, ///310
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(27.5),
//color: Colors.blue,
color: const Color(0xffffffff),
boxShadow: [
BoxShadow(
color: const Color(0x29000000),
offset: Offset(3, 3),
blurRadius: 6,
),
],
),
child: Padding(
padding: EdgeInsets.only(
left: 12 * SizeConfig.widthRatio,
right: 12 * SizeConfig.widthRatio,
top: 13 * SizeConfig.heightRatio,
bottom: 5 * SizeConfig.heightRatio),
child: TextFormField(
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 17 ,
color: const Color(0xd9343f4b),
fontFamily: 'Lato'),
//textAlign: TextAlign.left,
maxLines: null,
textCapitalization: TextCapitalization.sentences,
controller: myController,
decoration: InputDecoration.collapsed(
hintStyle: TextStyle(
color: Color(0x80343f4b),
fontFamily: 'Lato',
fontSize: 15 ,
//color: const Color(0xd9343f4b),
),
// hintStyle: ,
hintText: 'Enter Comment'),
),
),
), //Padding
//),
);
const String _svg_52blhh = //send
'<svg viewBox="332.0 762.0 20.0 20.0" ><path transform="translate(332.0, 762.0)" d="M 18.59535026550293 0.1261749565601349 L 0.4879408478736877 10.56938934326172 C -0.2191661894321442 10.97555732727051 -0.1293128132820129 11.95973491668701 0.5738875865936279 12.25654983520508 L 4.726676464080811 13.99838733673096 L 15.95053577423096 4.109749794006348 C 16.16540145874023 3.918381690979004 16.47012329101562 4.211291790008545 16.28650856018066 4.433903217315674 L 6.875344276428223 15.89644432067871 L 6.875344276428223 19.04034423828125 C 6.875344276428223 19.96203422546387 7.988744735717773 20.32524108886719 8.535677909851074 19.65740776062012 L 11.01641273498535 16.63848304748535 L 15.88412189483643 18.6771354675293 C 16.43886947631836 18.91146278381348 17.07174873352051 18.56387710571289 17.1733226776123 17.96634101867676 L 19.98612403869629 1.094730377197266 C 20.11895179748535 0.3058263659477234 19.27120399475098 -0.2643715739250183 18.59535026550293 0.1261749565601349 Z" fill="#343f4b" stroke="none" stroke- stroke-miterlimit="10" stroke-linecap="butt" /></svg>';
const String _svg_nznkw8 =
'<svg viewBox="24.0 762.0 22.0 22.0" ><path transform="translate(24.0, 762.0)" d="M 20.4285717010498 8.642857551574707 L 13.35714244842529 8.642857551574707 L 13.35714244842529 1.571428537368774 C 13.35714244842529 0.703705370426178 12.65343761444092 0 11.7857141494751 0 L 10.2142858505249 0 C 9.346562385559082 0 8.642857551574707 0.703705370426178 8.642857551574707 1.571428537368774 L 8.642857551574707 8.642857551574707 L 1.571428537368774 8.642857551574707 C 0.703705370426178 8.642857551574707 0 9.346562385559082 0 10.2142858505249 L 0 11.7857141494751 C 0 12.65343761444092 0.703705370426178 13.35714244842529 1.571428537368774 13.35714244842529 L 8.642857551574707 13.35714244842529 L 8.642857551574707 20.4285717010498 C 8.642857551574707 21.29629516601562 9.346562385559082 22 10.2142858505249 22 L 11.7857141494751 22 C 12.65343761444092 22 13.35714244842529 21.29629516601562 13.35714244842529 20.4285717010498 L 13.35714244842529 13.35714244842529 L 20.4285717010498 13.35714244842529 C 21.29629516601562 13.35714244842529 22 12.65343761444092 22 11.7857141494751 L 22 10.2142858505249 C 22 9.346562385559082 21.29629516601562 8.642857551574707 20.4285717010498 8.642857551574707 Z" fill="#343f4b" stroke="none" stroke- stroke-miterlimit="10" stroke-linecap="butt" /></svg>';
【问题讨论】:
【参考方案1】:首先你应该为你的SingleChildScrollView
定义一个控制器
ScrollController _scrollController = new ScrollController();
然后将其定义为它的控制器
SingleChildScrollView(
controller: _scrollController,
那么在TextField中就可以使用onTap函数了
Form(
child: TextFormField(
onTap: ()
_scrollController
.jumpTo(_scrollController.position.maxScrollExtent);
,
onSaved: (str) ,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email Address',
hintText: 'you@example.com',
),
),
),
每当用户点击文本字段屏幕跳到底部时使用代码 你也可以用这个代码而不是那个来动画它
onTap:()
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
【讨论】:
您好,我编辑了问题以澄清我的问题。为了清楚起见,我试图让聊天栏随着键盘上升。 每当用户点击文本字段并想写点什么,对吧? 我已经更新了我的代码,尝试一下并告诉我结果 我也没有运气,因为你在指定包装单个子滚动视图的位置,我将它包装在几乎每个小部件中,但没有得到预期的结果以上是关于如何使底栏随键盘向上移动(颤动)的主要内容,如果未能解决你的问题,请参考以下文章
当使用 Swift 出现键盘时如何向上移动 UIViewController 的内容