How to make the bottom bar move up with the keyboard (flutter)

1

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:

  1. 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.

  2. Padding the stack using bottom: MediaQuery.of(context).viewInsets.bottom, This causes the same undesirable outcome as above in #1

  3. 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>';

photo of the chat bar

flutter
dart
keyboard
textfield
asked on Stack Overflow Nov 19, 2020 by Isis Curiel • edited Nov 20, 2020 by Isis Curiel

1 Answer

1

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: 'you@example.com',
                ),
              ),
            ),

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);       
}
answered on Stack Overflow Nov 19, 2020 by yahya parvar • edited Nov 21, 2020 by yahya parvar

User contributions licensed under CC BY-SA 3.0