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

Pan*_*m T 10 dart flutter

当键盘出现时,我遇到了重建小部件的问题。我尝试使用 sizer 包,但永远无法弄清楚如何让它工作,当我从这个屏幕返回时,前一个屏幕中的所有内容都将重建,请注意:如果我不单击键盘,则typeaheadwidget键盘不会单击t 显示状态保留在前一个屏幕中,但一旦键盘弹出,小部件就会重建,您可以检查一下吗?

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,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

小智 19

这是键盘弹出后小部件被重建的唯一原因。您的一个或多个小部件的大小取决于 MediaQuery。

您可以尝试从 LayoutBuilder 获取屏幕尺寸作为 MediaQuery 的替代方案。


cam*_*024 6

您不应该尝试控制何时build调用该方法。buildFlutter 将在决定需要时调用(例如键盘出现、设备旋转、父级重建等)。

相反,您应该确保您的构建方法是“纯”函数。具体来说,在 Flutter 中,这意味着您不应执行任何具有“副作用”的操作(基本上是修改应用程序状态的任何操作)。

例如:

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 ...;
}
Run Code Online (Sandbox Code Playgroud)

相反,您应该将具有副作用的逻辑移至其他生命周期方法(例如initState()didChangeDepencencies()等)。

例如,如果您想在文本字段首次出现时将其设置为特定字符串,则可以使用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) {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

现在build()可以在需要时调用,而无需重置文本字段的状态。

请注意,即使有某种方法可以阻止您的小部件被重建,这也可能不是您想要的,因为 UI 不会更新以适应键盘。