【问题标题】:How to call SetState from another class如何从另一个类调用 SetState
【发布时间】:2021-08-03 17:55:48
【问题描述】:

希望有人可以帮助我。我有这种情况,我的文本字段已设置错误文本,因为用户单击继续而不选择值。据说,当我点击文本字段时,将显示一个对话框,其中包含我应该选择的数据列表。选择完成后,该值设置为文本字段,错误文本重置为空。但目前错误文本未重置为 null,它仍沿我选择的值显示。我在想可能是因为我需要通过调用 setstate 来重建 MySearchList 类。但我不知道该怎么做。希望任何人都可以告诉我什么是最好的方法来做到这一点。提前致谢。

导入'package:flutter/material.dart';

// ignore: must_be_immutable
class MySearchList extends StatefulWidget {
  MySearchList(
      {required this.label,
      required this.controller,
      required this.dataList,
      this.errorText});

  final String label;
  final TextEditingController controller;
  final List<String> dataList;
  String? errorText;

  @override
  _MySearchListState createState() => _MySearchListState();
}

class _MySearchListState extends State<MySearchList> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: TextField(
          decoration: InputDecoration(
            labelText: widget.label,
            errorText: widget.errorText,
          ),
          readOnly: true,
          controller: widget.controller,
          onTap: () {
            showDialog(
                context: context,
                builder: (BuildContext context) {
                  return MySearchListDialog(
                    label: widget.label,
                    controller: widget.controller,
                    dataList: widget.dataList,
                  );
                });
          }),
    );
  }
}

// ignore: must_be_immutable
class MySearchListDialog extends StatefulWidget {
  MySearchListDialog(
      {required this.label,
      required this.controller,
      required this.dataList,
      this.errorText});

  final String label;
  final TextEditingController controller;
  final List<String> dataList;
  String? errorText;

  @override
  _MySearchListDialogState createState() => _MySearchListDialogState();
}

class _MySearchListDialogState extends State<MySearchListDialog> {
  TextEditingController _textController = TextEditingController();
  List<String> _mainDataList = [];
  List<String> _newDataList = [];

  @override
  void initState() {
    super.initState();
    _mainDataList = widget.dataList;
    _newDataList = List.from(_mainDataList);
  }

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  onItemChanged(String value) {
    setState(() {
      _newDataList = _mainDataList
          .where((string) => string.toLowerCase().contains(value.toLowerCase()))
          .toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Dialog(
        child: Container(
      constraints: BoxConstraints(
        minHeight: 300.0,
        maxHeight: 400.0,
      ),
      child: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.fromLTRB(12.0, 10.0, 12.0, 0.0),
            child: MyTextField(
              hintLabel: "Search",
              controller: _textController,
              onChanged: onItemChanged,
              errorText: widget.errorText,
            ),
          ),
          Expanded(
            child: ListView(
              padding: EdgeInsets.all(12.0),
              children: _newDataList.map((data) {
                return ListTile(
                    title: Text(data),
                    onTap: () {
                      //this setstate will not rebuild class MySearchList
                      setState(() {
                        widget.errorText = null; //reset error on textfield
                        widget.controller.text = data.toString(); //set value to textfield
                        Navigator.pop(context); //close dialog
                      });
                    });
              }).toList(),
            ),
          )
        ],
      ),
    ));
  }
}

【问题讨论】:

  • 您将控制器发送到对话框,并且从对话框中您将文本设置到控制器,但我认为正确的方法是将事件发送到 onTextSelected() 之类的对话框并处理在 MySearchList 和里面,甚至执行 setState 来设置文本和重置错误文本。
  • 为什么不使用link中解释的回调机制。
  • 感谢您的反馈,我将尝试查看这两种解决方案。再次感谢您

标签: flutter flutter-layout


【解决方案1】:

像这样显示你的对话框:

_MySearchListState

onTap: () async {
  var data = await showDialog(
    context: context,
    builder: (BuildContext context) {
    return MySearchListDialog(
      label: widget.label,
      controller: widget.controller,
      dataList: widget.dataList,
     );
  });
  if(null != data){
    setState(() {
   
    });
  }
})

然后像这样关闭你的对话框:

_MySearchListDialogState

onTap: () {
  //this setstate will not rebuild class MySearchList
  setState(() {
    widget.errorText = null; //reset error on textfield
    widget.controller.text = data.toString(); //set value to textfield
  });
  Navigator.of(context).pop(data); // <-- Pass data and close dialog
});

【讨论】:

  • 非常感谢!我不知道为什么我没有想到这一点。谢谢!
猜你喜欢
  • 2019-07-14
  • 2021-05-04
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多