【问题标题】:Multiple Select in DropdownButton in flutter颤动中的DropdownButton中的多项选择
【发布时间】:2021-05-31 17:06:06
【问题描述】:

我知道有很多方法/包可以在颤动的下拉按钮中实现多选,例如 --> this one 但以我所知甚少,我想为基础建筑重新发明轮子!!!

我的场景 ->

我有一个像这样的 json 格式的位置列表 -->

[{id: 928, location: Amtoli}, {id: 905, location: Ashok Tala}, {id: 899, location: Badur Tola}]

还有两个List -->

List _location = new List(); // this comes from API;
List _multiSelectLoc = new List();

DropDownButtononChanged 属性中 -->

    onChanged: (newValue) {
setState(() {
  _location.forEach((e) {
  if (e["id"] == newValue.toString()) {
    _multiSelectLoc.add(e);
    print(_multiSelectLoc);
  }
});
  _location.removeWhere(
      (e) => e['id'] == newValue.toString());
  print(_location);
});
},

我很想知道为什么我的代码不工作,为什么我不能从 List _location 中删除数据,并添加到 List _multiSelectLoc

我已经在 dartpad 中模拟了这样的情况,它刚刚好!

【问题讨论】:

    标签: flutter dart dropdownbutton


    【解决方案1】:

    您可以使用自定义小部件来做到这一点,例如:

    class MultiSelectDialogItem<V> {
      const MultiSelectDialogItem(this.value, this.label);
    
      final V value;
      final String label;
    }
    
    class MultiSelectDialog<V> extends StatefulWidget {
      MultiSelectDialog({Key key, this.items, this.initialSelectedValues}) : super(key: key);
    
      final List<MultiSelectDialogItem<V>> items;
      final Set<V> initialSelectedValues;
    
      @override
      State<StatefulWidget> createState() => _MultiSelectDialogState<V>();
    }
    
    class _MultiSelectDialogState<V> extends State<MultiSelectDialog<V>> {
      final _selectedValues = Set<V>();
    
      void initState() {
        super.initState();
        if (widget.initialSelectedValues != null) {
          _selectedValues.addAll(widget.initialSelectedValues);
        }
      }
    
      void _onItemCheckedChange(V itemValue, bool checked) {
        setState(() {
          if (checked) {
            _selectedValues.add(itemValue);
          } else {
            _selectedValues.remove(itemValue);
          }
        });
      }
    
      void _onCancelTap() {
        Navigator.pop(context);
      }
    
      void _onSubmitTap() {
        Navigator.pop(context, _selectedValues);
      }
    
      @override
      Widget build(BuildContext context) {
        return AlertDialog(
          title: Text('Select animals'),
          contentPadding: EdgeInsets.only(top: 12.0),
          content: SingleChildScrollView(
            child: ListTileTheme(
              contentPadding: EdgeInsets.fromLTRB(14.0, 0.0, 24.0, 0.0),
              child: ListBody(
                children: widget.items.map(_buildItem).toList(),
              ),
            ),
          ),
          actions: <Widget>[
            FlatButton(
              child: Text('CANCEL'),
              onPressed: _onCancelTap,
            ),
            FlatButton(
              child: Text('OK'),
              onPressed: _onSubmitTap,
            )
          ],
        );
      }
    
      Widget _buildItem(MultiSelectDialogItem<V> item) {
        final checked = _selectedValues.contains(item.value);
        return CheckboxListTile(
          value: checked,
          title: Text(item.label),
          controlAffinity: ListTileControlAffinity.leading,
          onChanged: (checked) => _onItemCheckedChange(item.value, checked),
        );
      }
    }
    

    之后使用如下:

    void _showMultiSelect(BuildContext context) async {
      final items = <MultiSelectDialogItem<int>>[
        MultiSelectDialogItem(1, 'Dog'),
        MultiSelectDialogItem(2, 'Cat'),
        MultiSelectDialogItem(3, 'Mouse'),
      ];
    
      final selectedValues = await showDialog<Set<int>>(
        context: context,
        builder: (BuildContext context) {
          return MultiSelectDialog(
            items: items,
            initialSelectedValues: [1, 3].toSet(),
          );
        },
      );
    
      print(selectedValues);
    }
    

    【讨论】:

    • 我知道,正如我在第一行中提到的那样,我可以通过多种方式实现它,但是我对我的代码很感兴趣,也就是说,我想知道我的方式有什么问题做。
    【解决方案2】:

    我想我发现了问题,

    重写代码-->

    onChanged: (newValue) {
                          _location.forEach((e) {
                            if (e['id'].toString() == newValue.toString()) {
                              _multiSelectLoc.add(e);
                              // print(_multiSelectLoc);
                            }
                          });
                          _location.removeWhere(
                              (e) => e['id'].toString() == newValue.toString());
                          setState(() {
                            // print(_location);
                          });
                        },
    

    我认为问题是,我使用动态类型与字符串类型进行比较,当我添加.toString() 时,代码开始给我结果!

    【讨论】:

      猜你喜欢
      • 2021-10-09
      • 2021-01-27
      • 2021-04-02
      • 1970-01-01
      • 2020-11-10
      • 2021-09-04
      • 2020-05-07
      • 2020-02-06
      • 2020-02-08
      相关资源
      最近更新 更多