简体   繁体   English

为什么我的小部件在我使用键盘时重建

[英]Why does my widget rebuild when I use keyboard

I have this issue of rebuilding widget when The keyboards shows up.当键盘出现时,我遇到了重建小部件的问题。 I tried to use the sizer package but never could figure out how to get it to work when I go back from this screen everything in the previous screen will rebuild, Please note: If I don't click on the typeaheadwidget such that the keyboard doesn't show up the state is preserved in the previous screen but as soon as the keyboard pops up the widgets get rebuilt Could you please check?我尝试使用 sizer package,但是当我从该屏幕返回 go 时,我一直无法弄清楚如何让它工作,之前屏幕中的所有内容都将重建,请注意:如果我不单击typeaheadwidget ,则键盘不会't show up state 保留在前一个屏幕中,但一旦弹出键盘,小部件就会重建 你能检查一下吗?

class SearchScreen extends StatefulWidget {
  @override
  _SearchScreenState createState() => _SearchScreenState();
}

class _SearchScreenState extends State<SearchScreen> {
  TextEditingController pickUpTextEditingController = TextEditingController();
  TextEditingController dropOffTextEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();
  }

  @override
  @mustCallSuper
  Widget build(BuildContext context) {
    String placeAddress =
        Provider.of<AppData>(context).pickUpLocation.placeName ?? "";
    pickUpTextEditingController.text = placeAddress;

    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Stack(
        children: [
          Container(
            height: 250.0,
            decoration: BoxDecoration(
              color: Colors.white,
              boxShadow: [
                BoxShadow(
                  color: Colors.black,
                  blurRadius: 6.0,
                  spreadRadius: 0.5,
                  offset: Offset(0.7, 0.7),
                )
              ],
            ),
            child: Padding(
              padding: EdgeInsets.only(
                  left: 25.0, top: 30.0, right: 25.0, bottom: 20.0),
              child: Column(
                children: [
                  SizedBox(height: 5.0),
                  Stack(
                    children: [
                      GestureDetector(
                          onTap: () {
                            Navigator.pop(
                                //send back data
                                context,
                                dropOffTextEditingController.text);
                          },
                          child: Icon(Icons.arrow_back)),
                      Center(
                        child: Text(
                          "Set Drop Off",
                          style: TextStyle(
                              fontSize: 18.0, fontFamily: "Brand-Bold"),
                        ),
                      )
                    ],
                  ),
                  SizedBox(height: 16.0),
                  Row(
                    children: [
                      Image.asset("images/images/pickicon.png",
                          height: 16.0, width: 16.0),
                      SizedBox(width: 18.0),
                      Expanded(
                          child: Container(
                        decoration: BoxDecoration(
                          color: Colors.grey[400],
                          borderRadius: BorderRadius.circular(5.0),
                        ),
                        child: Padding(
                          padding: EdgeInsets.all(3.0),
                          child: TextField(
                            controller: pickUpTextEditingController,
                            decoration: InputDecoration(
                              hintText: "PickUp Location",
                              fillColor: Colors.grey[400],
                              filled: true,
                              border: InputBorder.none,
                              isDense: true,
                              contentPadding: EdgeInsets.only(
                                  left: 11.0, top: 8.0, bottom: 8.0),
                            ),
                          ),
                        ),
                      ))
                    ],
                  ),
                  SizedBox(height: 10.0),
                  Row(
                    children: [
                      Image.asset("images/images/desticon.png",
                          height: 16.0, width: 16.0),
                      SizedBox(width: 18.0),
                      Expanded(
                        child: Container(
                          decoration: BoxDecoration(
                            color: Colors.grey[400],
                            borderRadius: BorderRadius.circular(5.0),
                          ),
                          child: Padding(
                            padding: EdgeInsets.all(3.0),
                            child: TypeAheadField(
                              itemBuilder: null,
                              onSuggestionSelected: null,
                              suggestionsCallback: null,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

You should not try to control when the build method is called.您不应该尝试控制何时调用build方法。 Flutter will call build when it decides it needs to (eg keyboard appears, device rotated, parent rebuilds, etc). Flutter 将在需要时调用build (例如,键盘出现、设备旋转、父级重建等)。

Instead, you should make sure that your build method is a "pure" function.相反,您应该确保您的构建方法是“纯”函数。 In Flutter specifically, this means that you should not perform any action with "side-effects" (basically anything which modifies the state of the app).特别是在 Flutter 中,这意味着您不应该执行任何带有“副作用”的操作(基本上是任何修改应用程序状态的操作)。

For example:例如:

Widget build(BuildContext context) {
  final x = 2 + 3;  // fine, nothing else is modified
  final state = context.watch<MyModel>();  // also fine, only reading data
  controller.text = "hello";  // BAD, modifies the state of the app

  return ...;
}

Instead, you should move your logic with side effects into other lifecycle methods (eg initState() , didChangeDepencencies() , etc).相反,您应该将具有副作用的逻辑移至其他生命周期方法(例如initState()didChangeDepencencies()等)。

For example, if you want to set your text field to a particular string when it first appears, you can use initState :例如,如果您想在文本字段首次出现时将其设置为特定字符串,您可以使用initState

class _SearchScreenState extends State<SearchScreen> {
  @override
  void initState() {
    super.initState();
    final data = context.read<AppData>();
    controller.text = data.pickUpLocation.placeName ?? "";
  }

  Widget build(BuildContext context) {
    // ...
  }
}

Now build() can be called whenever it has to be, without resetting the state of your text field.现在build()可以随时调用,而无需重置文本字段的状态。

Note that, even if there was some way to prevent your widget from being rebuilt, this is also likely not what you want, since the UI would not update to accommodate the keyboard.请注意,即使有某种方法可以防止您的小部件被重建,这也可能不是您想要的,因为 UI 不会更新以适应键盘。

the only reason why your widgets got rebuilds after keyboard pop up.键盘弹出后您的小部件重建的唯一原因。 is that one or more of your widgets size depends on MediaQuery.是您的一个或多个小部件大小取决于 MediaQuery。

you can try to ge your screen size from LayoutBuilder as an alternative for MediaQuery.您可以尝试从 LayoutBuilder 获取屏幕大小作为 MediaQuery 的替代方案。

When you tap the TextField widget, it makes the keyboard show up.当您点击TextField小部件时,它会显示键盘。 And when the keyboard shows up, your screen size changes.当键盘出现时,您的屏幕尺寸会发生变化。 This causes the rebuild这导致重建

`give the textfield initial value like this: initvalue:Provider.of(context).pickUpLocation.placeName?? `像这样给文本字段初始值:initvalue:Provider.of(context).pickUpLocation.placeName?? "" “”

and use onchange method in text feild instead of text editing controller like this: onchange(value){ Provider.of(context).pickUpLocation.placeName=value;}`并在文本字段中使用 onchange 方法,而不是像这样编辑 controller:onchange(value){ Provider.of(context).pickUpLocation.placeName=value;}`

I am also facing the same issue, My blocBuidler is getting rebuilt every time when click on textfield or keyboard is appear.我也面临同样的问题,每次单击文本字段或出现键盘时,我的 blocBuidler 都会重建。

In my case, I was calling the event in parent BlocBuilder so whenever I pressed on textfields the parent BlocBuilder is called the event, so it builds state of child BlocBuilder在我的例子中,我在父 BlocBuilder 中调用事件,所以每当我按下文本字段时,父 BlocBuilder 就被称为事件,因此它构建了子 BlocBuilder 的 state

Make sure you are also doing the same thing.确保你也在做同样的事情。 If you are doing the same thing please check the state whether it is already built or not.如果您正在做同样的事情,请检查 state 是否已经构建。

(BlocProvider.of<YourBlocName>(context).state is YouBlocState) ?  Print('do nothing'): BlocProvider.of<YourBlocName>(context).add(youBlocEvent);

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

相关问题 当键盘出现时,我的整个小部件树会重建吗? - Will my whole widget tree rebuild when a keyboard appears? 为什么当我在无状态小部件中点击 textField 时,它会重建小部件? - Why when I tap textField in stateless widget it will rebuild widget? 为什么在 flutter 中的 setState() 之后我的 statefull 小部件无法正确重建? - Why does my statefull widget not rebuild properly after setState() in flutter? 出现键盘时重建整个小部件树 - Rebuild whole widget tree when a keyboard appears flutter 当 api 更改时,我如何重建我的小部件? - flutter how can i rebuild my widget when api change? 有状态的小部件无法重建 - Stateful widget does not rebuild 我希望我的底部小部件在键盘聚焦时推到顶部 - i want my bottom widget to push on top when keyboard focused 仅当屏幕尺寸宽度为特定数字时,如何才能重建我的小部件 - How can I get my widget to rebuild only when screen size width is certain number Flutter 有状态小部件不重建 - Flutter Stateful widget does not rebuild setState() 在我的小部件中不起作用,因为我的小部件构建在小部件树的底部,那么我如何重建该小部件? - setState() is not working inside my widget, since my that widget is built on the bottom of the widget tree, then how can I rebuild that widget?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM