简体   繁体   English

Flutter TextFormField 聚焦时重新加载当前屏幕

[英]Flutter TextFormField reloads current screen when focused

I have a TextFormField that reloads the current screen when I tap on it to enter text.我有一个 TextFormField,当我点击它输入文本时它会重新加载当前屏幕。 When I tap on the formfield the software keyboard is displayed briefly before the entire screen reloads and renders all the widgets again.当我点击表单域时,软件键盘会在整个屏幕重新加载并再次呈现所有小部件之前短暂显示。 I am running the app on an Android device.我正在 Android 设备上运行该应用程序。

Container(
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextFormField(
                validator: (value) {
                  if (value.isEmpty) {
                    return 'Your input cannot be empty';
                  }
                },
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16.0),
                child: RaisedButton(
                  onPressed: () {

                    if (_formKey.currentState.validate()) {
                      print('validated');
                    }
                  },
                  child: Text('Save'),
                ),
              ),
            ],
          ),
        ),
        margin: EdgeInsets.only(top:8.0),
  ),

The problem is that the controller of the TextFormField is rebuild when you click on the field, and that's the reason of your issue.问题是当您单击该字段时,TextFormField 的控制器正在重建,这就是您的问题的原因。

So to solve that, did you try to create a Statefull widget and then creating a TextEditingController in the State of this widget and passing it as an argument to the TextFormField ?所以为了解决这个问题,您是否尝试创建一个 Statefull 小部件,然后在这个小部件的状态中创建一个 TextEditingController 并将其作为参数传递给 TextFormField ?

I had the same Problem.我有同样的问题。 this was my code这是我的代码

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Model model = Model();

  @override
  Widget build(BuildContext context) {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
    var mediaWidth = MediaQuery.of(context).size.width / 2.0;
    return Scaffold(
...

and I solved this problem by declaring the _formKey outside of build method.我通过在 build 方法之外声明 _formKey 解决了这个问题。 and this worked for me.这对我有用。

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Model model = Model();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    var mediaWidth = MediaQuery.of(context).size.width / 2.0;
    return Scaffold(
...

hope it will help you希望它会帮助你

Check if you are using MediaQueries wrongly in your project, I had similar issue and it stopped when I changed the MediaQuery in my case:检查您是否在项目中错误地使用了 MediaQueries,我遇到了类似的问题,并且在我更改MediaQuery时它停止了:

Size _size = MediaQuery.of(context).size;

removing this piece of code fixed my app.删除这段代码修复了我的应用程序。

I have the same issue anyone can solve this error please....我有同样的问题任何人都可以解决这个错误请....

Material(
      child: Scaffold(
        appBar: AppBar(
          leading: IconButton(
              onPressed: () {
                Navigator.pop(context);
              },
              icon: Icon(
                Icons.arrow_back_ios_new,
                size: 16,
                color: Colors.black,
              )),
          title: Text(
            "Review Page",
            style: TextStyle(color: Colors.blue),
          ),
          backgroundColor: Colors.transparent,
          elevation: 0,
        ),
        body: GestureDetector(
          onTap: () {
            FocusScope.of(context).requestFocus(new FocusNode());
          },
          child: StreamBuilder(
              stream: reviewStream,
              builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return Center(child: CircularProgressIndicator());
                }
                final List reviewList = [];
                snapshot.data!.docs.map((DocumentSnapshot e) {
                  Map dataList = e.data() as Map<String, dynamic>;
                  reviewList.add(dataList);
                }).toList();
                final Stream<QuerySnapshot> reviewDisplayStream =
                    FirebaseFirestore.instance
                        .collection("customer")
                        .where("uid", isEqualTo: userId)
                        .snapshots();
                return SafeArea(
                  child: userId == ""
                      ? logincommentChild(reviewList)
                      : StreamBuilder(
                          stream: reviewDisplayStream,
                          builder:
                              (context, AsyncSnapshot<QuerySnapshot> snapshot) {
                            if (snapshot.connectionState ==
                                ConnectionState.waiting) {
                              return Center(child: CircularProgressIndicator());
                            }
                            final List reviewDisplayList = [];
                            snapshot.data!.docs.map((DocumentSnapshot e) {
                              Map dataList = e.data() as Map<String, dynamic>;
                              reviewDisplayList.add(dataList);
                            }).toList();
                            return Container(
                                child: CommentBox(
                              userImage: reviewDisplayList[0]['image'] != ''
                                  ? reviewDisplayList[0]['image']
                                  : "https://firebasestorage.googleapis.com/v0/b/fir-prictice-81c0f.appspot.com/o/profile.png?alt=media&token=8fdf702b-8f5a-4a12-b46a-091758812a5d",
                              child: commentChild(
                                  reviewList), //display review of cusotmer....
                              labelText: 'Write a breif review...',
                              withBorder: true,
                              errorText: 'Review cannot be blank',
                              sendButtonMethod: () {
                                if (formKey.currentState!.validate()) {
                                  print(commentController.text);
                                  setState(() async {
                                    Map<String, dynamic> value = {
                                      'name': reviewDisplayList[0]['name'],
                                      'pic': reviewDisplayList[0]['image'] != ''
                                          ? reviewDisplayList[0]['image']
                                          : "https://firebasestorage.googleapis.com/v0/b/fir-prictice-81c0f.appspot.com/o/profile.png?alt=media&token=8fdf702b-8f5a-4a12-b46a-091758812a5d",
                                      'message': commentController.text,
                                      'date and time': date
                                    };
                                    FirebaseFirestore.instance
                                        .collection("Review")
                                        .add(value);
                                  });
                                  commentController.clear();
                                  FocusScope.of(context).unfocus();
                                } else {
                                  print("Not validated");
                                }
                              },
                              formKey: formKey,
                              commentController: commentController,
                              backgroundColor: Colors.blue,
                              textColor: Colors.white,
                              sendWidget: Icon(Icons.send_sharp,
                                  size: 24, color: Colors.white),
                            ));
                          }),
                );
              }),
        ),
        bottomNavigationBar: footer(
          tabIndex: 2,
        ),
      ),
    );

When TextFormField focused the size of screen will changed because of the appearance of keyboard, that cause rebuild of state, you cant prevent re-build of state.TextFormField聚焦时,屏幕的大小会因为键盘的出现而改变,导致状态的重建,你不能阻止状态的重建。

Instead of trying prevent re-build state , you need to solve problems which happen when state do re-build, one of common problem is declaration and initialization variables inside build(BuildContext context){ ... }' function.而不是试图阻止重新构建状态,您需要解决状态重新构建时发生的问题,常见问题之一是build(BuildContext context){ ... }'函数中的声明和初始化变量。

The main problem, when you need to get some data related of context (like size of screen), in this case I prefer to pass this value from parent Widget ...主要问题是,当您需要获取一些与context相关的数据(如屏幕大小)时,在这种情况下,我更喜欢从父Widget传递这个值......

For example this code will cause problem when re-build state:例如,此代码在重新构建状态时会导致问题:

  @override
  Widget build(BuildContext context) {
    double? _screenHeight =  MediaQuery.of(context).size.height;
    return Container();
  }

To solve problem get _screenHeight from parent, to know how to do that look at https://stackoverflow.com/a/50289032/2877427要解决问题, _screenHeight从父级获取_screenHeight ,要知道如何做到这一点,请查看https://stackoverflow.com/a/50289032/2877427

Yes, that happens because when the keyboard appears, the flutter scaffold gets resize to the current available screen size.是的,发生这种情况是因为当键盘出现时,flutter scaffold 会调整为当前可用的屏幕大小。 So, we can easily handle this by preventing the scaffold size change.因此,我们可以通过防止脚手架尺寸变化来轻松处理这个问题。 I suggest to set scaffold resizeToAvoidBottomInset property false.我建议将脚手架 resizeToAvoidBottomInset 属性设置为 false。 If it's true the body and the scaffolds floating widgets should size themselves to avoid the onscreen keyboard whose height is defined by the ambient MediaQuery's, MediaQueryData,viewInsets bottom property.如果确实如此,则主体和脚手架浮动小部件应自行调整大小,以避免出现高度由环境 MediaQuery、MediaQueryData、viewInsets 底部属性定义的屏幕键盘。

Solution:解决方案:

resizeToAvoidBottomInset: false,

Complete example:完整示例:

@override
Widget build(BuildContext context) {
  setDisplayData();
  return Scaffold(
    resizeToAvoidBottomInset: false,
    appBar: getAppBar(),
    body: OrientationBuilder(
      builder: (context, orientation) {
        return orientation == Orientation.portrait
            ? _buildVerticalLayout()
            : _buildHorizontalLayout();
      },
    ),
  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM