Search code examples
flutterkeyboardfocusscrollcontroller

How to push content up when focus is on TextField and keyboard opens in Flutter?


I need to push my content up when the focus is on 'Description' TextField and the keyboard opens

Without keyboard:

Without keyboard

Actual result

Actual result

Expected result

Actual result

       ListView(
        children: [
          Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Title'),
                  TitleField(
                    controller: titleEditingController,
                  ),
                  Text(
                    'Description',
                  ),
                  DescriptionField(
                      focusNode: _focusNode,
                      controller: descriptionEditingController),
                  DCDatePicker(),
                ],
              ),
              AddButton(),
            ],
          ),
        ],
      );

Solution

  • Please refer to below code

    Using ScrollController you can scroll to bottom when Description TextField is onTapped and onFocus by adding this piece of code

     _controller.animateTo(
                        _controller.position.maxScrollExtent,
                        duration: Duration(seconds: 1),
                        curve: Curves.fastOutSlowIn,
                      );
    
    
    
    final _controller = ScrollController();
    
    ListView(
              controller: _controller,
              children: [
                   Column(
                    children: [
                      Text('Title'),
                      TitleField(
                        controller: titleEditingController,
                      ),
                      Text(
                        'Description',
                      ),
                      DescriptionField(
                          focusNode: _focusNode,
                          controller: descriptionEditingController),
                      DCDatePicker(),
                    ],
                  ),
                     
                SizedBox(
                  height: 15.0,
                ),
                AddButton(),
                
                SizedBox(
                  height: 250.0,
                ), // Add space at end of list view so it allows to scroll
              ],
            ),
          
    

    Please refer to below example code

    class MainScreen extends StatefulWidget {
      MainScreen({Key key}) : super(key: key);
    
      @override
      _MainScreenState createState() => _MainScreenState();
    }
    
    class _MainScreenState extends State<MainScreen> {
      final TextEditingController emailController = TextEditingController();
    
      final FocusNode emailFocus = FocusNode();
    
      final TextEditingController pswdController = TextEditingController();
    
      final FocusNode pswdFocus = FocusNode();
    
      final _validationKey = GlobalKey<FormState>();
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      int validateEmail(String emailAddress) {
        String patttern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$';
        RegExp regExp = new RegExp(patttern);
        if (emailAddress.isEmpty || emailAddress.length == 0) {
          return 1;
        } else if (!regExp.hasMatch(emailAddress)) {
          return 2;
        } else {
          return 0;
        }
      }
    
      int validatePassword(String pswd) {
        if (pswd.isEmpty || pswd.length == 0) {
          return 1;
        } else if (pswd != null && pswd.isNotEmpty && pswd.length <= 8) {
          return 2;
        } else {
          return 0;
        }
      }
    
      final _controller = ScrollController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.lightBlue,
            automaticallyImplyLeading: true,
            leading: Icon(
              Icons.arrow_back,
            ),
            title: Text("Example"),
            centerTitle: true,
          ),
          body: Container(
            padding: EdgeInsets.all(15.0),
            child: ListView(
              controller: _controller,
              children: [
                Form(
                  key: _validationKey,
                  child: Column(
                    children: [
                      /* Email */
                      TextFormField(
                        autovalidateMode: AutovalidateMode.onUserInteraction,
                        /* autovalidate is disabled */
                        controller: emailController,
                        keyboardType: TextInputType.emailAddress,
                        onChanged: (val) {},
                        maxLines: 1,
                        validator: (value) {
                          int res = validateEmail(value);
                          if (res == 1) {
                            return "Please  fill email address";
                          } else if (res == 2) {
                            return "Please enter valid email address";
                          } else {
                            return null;
                          }
                        },
                        focusNode: emailFocus,
                        autofocus: false,
                        decoration: InputDecoration(
                          errorMaxLines: 3,
                          counterText: "",
                          filled: true,
                          fillColor: Colors.white,
                          focusedBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          disabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          enabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                            ),
                          ),
                          errorBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(4)),
                              borderSide: BorderSide(
                                width: 1,
                                color: Colors.red,
                              )),
                          focusedErrorBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Colors.red,
                            ),
                          ),
                          hintText: "Enter email address" ?? "",
                        ),
                      ),
                      SizedBox(
                        height: 15.0,
                      ),
    
                      /* Password */
                      TextFormField(
                        autovalidateMode: AutovalidateMode.onUserInteraction,
                        /* autovalidate is disabled */
                        controller: pswdController,
                        inputFormatters: [
                          FilteringTextInputFormatter.deny(RegExp(r"\s\s")),
                          FilteringTextInputFormatter.deny(RegExp(
                              r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
                        ],
                        keyboardType: TextInputType.text,
                        onChanged: (val) {},
                        maxLines: 15,
                        validator: (value) {
                          int res = validatePassword(value);
                          if (res == 1) {
                            return "Please enter password";
                          } else if (res == 2) {
                            return "Please enter minimum 9 characters";
                          } else {
                            return null;
                          }
                        },
                        focusNode: pswdFocus,
                        autofocus: false,
                        onTap: () {
                          _controller.animateTo(
                            _controller.position.maxScrollExtent,
                            duration: Duration(seconds: 1),
                            curve: Curves.fastOutSlowIn,
                          );
                        },
                        decoration: InputDecoration(
                          errorMaxLines: 3,
                          counterText: "",
                          filled: true,
                          fillColor: Colors.white,
                          focusedBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          disabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          enabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Color(0xffE5E5E5),
                            ),
                          ),
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                            ),
                          ),
                          errorBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(4)),
                              borderSide: BorderSide(
                                width: 1,
                                color: Colors.red,
                              )),
                          focusedErrorBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                            borderSide: BorderSide(
                              width: 1,
                              color: Colors.red,
                            ),
                          ),
                          hintText: "Enter password" ?? "",
                        ),
                      ),
                    ],
                  ),
                ),
                SizedBox(
                  height: 15.0,
                ),
                OutlinedButton(
                  onPressed: () {
                    _validationKey.currentState.validate();
                    if (emailController.text.isEmpty) {
                      emailFocus.requestFocus();
                    } else if (pswdController.text.isEmpty ||
                        pswdController.text.length <= 8) {
                      pswdFocus.requestFocus();
                      _controller.animateTo(
                        _controller.position.maxScrollExtent,
                        duration: Duration(seconds: 1),
                        curve: Curves.fastOutSlowIn,
                      );
                    }
                  },
                  child: Text("Validate"),
                ),
                SizedBox(
                  height: 250.0,
                ),
              ],
            ),
          ),
        );
      }
    }