当焦点在 TextField 上并且键盘在 Flutter 中打开时如何向上推送内容?

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

当焦点位于 'Description' TextField 且键盘打开时,我需要将我的内容上推

without keyboard

Actual result

Expected 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(),
            ],
          ),
        ],
      );

请参考以下代码

使用 ScrollController,当 Description TextField 处于 onTapped 和 onFocus 时,您可以通过添加这段代码滚动到底部

 _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
          ],
        ),
      

请参考下面的示例代码

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,
            ),
          ],
        ),
      ),
    );
  }
}