Reputation: 160
I am trying to have my chat bar (text field, the 2 buttons and the black bar behind the text field) rise up with the keyboard when it's engaged.
I have tried the following:
Wrapping the Stack with all the elements in a Positioned widget using bottom: MediaQuery.of(context).viewInsets.bottom
,
however, if i do this it gets rid of the 2 buttons and the black bar and does not raise the textfield when the keyboard is engaged.
Padding the stack using bottom: MediaQuery.of(context).viewInsets.bottom
,
This causes the same undesirable outcome as above in #1
Wrapping the stack in a single child scrollview: Move textfield up when keyboard appears in Flutter if i wrap the stack in a singlechildscrollview it does not move when the keyboard is engaged.
If anybody can guide me in the right direction, perhaps I'm wrapping them in the wrong widget or I have to use an animation to move the stack up.
the code is below:
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-width="1" 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-width="1" stroke-miterlimit="10" stroke-linecap="butt" /></svg>';
Upvotes: 2
Views: 1509
Reputation: 4848
first you should define an controller for your SingleChildScrollView
ScrollController _scrollController = new ScrollController();
then define it as a controller for it
SingleChildScrollView(
controller: _scrollController,
then in the TextFieldyou can use onTap function
Form(
child: TextFormField(
onTap: () {
_scrollController
.jumpTo(_scrollController.position.maxScrollExtent);
},
onSaved: (str) {},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email Address',
hintText: '[email protected]',
),
),
),
with code whenever user clicks on the textfield screen jumps to the bottom you can also animate it with this code instead of that
onTap:(){
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
}
Upvotes: 1