在ListView.builder()中检查/取消选中ListTiles-Flutter

时间:2018-10-15 18:18:16

标签: flutter

我在ListView.builder();中有一个showModalBottomSheet(); 需要选择/取消选择多个项目,一切都很好,但是需要关闭模式并再次显示以应用更改,另一件事是ListTiles有时重复多次,而功能emptyList却没有工作正常。

    import 'package:http/http.dart' as http;
    import 'dart:convert';
    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'book_details.dart' show BookDetails;

    class Explore extends StatefulWidget {
      @override
      _ExploreState createState() => _ExploreState();
    }

    var _books,
        _categories,
        _arranges,
        _currentCategory,
        _selected,
        _primeColor,
        _currentFilter,
        _isThereIsFilters,
        _booksContainer,
        _booksWithFilters,
        _isLoading,
        _noBooks,
        _itemIcon;

    final GlobalKey<ScaffoldState> _scaffoldKeyExplore =
        new GlobalKey<ScaffoldState>();

    List<String> _getCats = new List();
    List<String> _getArrs = new List();

    void _insertCategories() {
      for (int i = 0; i < _categories.length; i++) {
        _getCats.add(_categories[i]);
      }
      _getCats.sort();
    }

    void _insertArranges() {
      for (int i = 0; i < _arranges.length; i++) {
        _getArrs.add(_arranges[i]);
      }
    }

    class _ExploreState extends State<Explore> with TickerProviderStateMixin {

      onCatChange(String category) {
        setState(() {
          _currentCategory = category;
        });
      }

      @override
      void initState() {
        super.initState();
        _primeColor = Color.fromRGBO(239, 89, 39, 1.0);
        _categories = ["أول", "ثاني", "ثالث", "رابع", "خامس"];
        _arranges = ["أول", "ثاني", "ثالث", "رابع", "خامس"];
        _currentFilter = _arranges[0];
        _selected = [];
        _isThereIsFilters = false;
      }

      void emptyList(List list) {
        for (var i = 0; i < list.length; i++) {
          list.remove(list[i]);
        }
      }

      _showSheet(String type) {
        switch (type) {
          case "filters":
            showModalBottomSheet(
                context: _scaffoldKeyExplore.currentContext,
                builder: (BuildContext context) {
                  return Directionality(
                    textDirection: TextDirection.rtl,
                    child: Container(
                        child: Column(children: <Widget>[
                      Expanded(
                        child: new ListView.builder(
                            itemCount: _getArrs[0] != null ? _getArrs.length : 0,
                            itemBuilder: (BuildContext context, int i) {
                              return new RadioListTile(
                                  title: Text(_getArrs[i]),
                                  value: _getArrs[i],
                                  groupValue: _currentFilter,
                                  onChanged: (val) {
                                    setState(() {
                                      _currentFilter = val;
                                    });
                                  });
                            }),
                      )
                    ])),
                  );
                });
            break;

          case "categories":
          default:
            showModalBottomSheet(
                context: _scaffoldKeyExplore.currentContext,
                builder: (BuildContext context) {
                  return Directionality(
                    textDirection: TextDirection.rtl,
                    child: Container(
                        child: Column(children: <Widget>[
                          Container(
                            color: _primeColor,
                            child: Row(
                                mainAxisSize: MainAxisSize.max,
                                mainAxisAlignment: MainAxisAlignment.end,
                                children: <Widget>[
                                  IconButton(
                                      icon: Icon(Icons.close, color: Colors.white),
                                      onPressed: () {
                                        emptyList(_selected);
                                        //Navigator.pop(context);
                                        //_showSheet(type);
                                      }),
                                  IconButton(
                                      icon:
                                          Icon(Icons.done_all, color: Colors.white),
                                      onPressed: () {
                                        if (_selected.length > 0) {
                                          _getFilteredBooks(_selected);
                                          setState(() {
                                            _isThereIsFilters = true;
                                          });
                                        } else {
                                          setState(() {
                                            _isThereIsFilters = false;
                                          });
                                        }
                                        Navigator.pop(context);
                                      })
                                ]),
                          ),
                          Expanded(
                            child: new ListView.builder(
                                itemCount: _getCats != null ? _getCats.length : 0,
                                itemBuilder: (BuildContext context, int i) {
                                  final _isSelected = _selected.contains(_getCats[i]);
                                  return new ListTile(
                                      leading: Icon(Icons.category),
                                      trailing: _isSelected ? Icon(Icons.done) : null,
                                      title: Text(_getCats[i]),
                                      onTap: () {
                                        setState(() {
                                          _isSelected
                                              ? _selected.remove(_getCats[i])
                                              : _selected.add(_getCats[i]);
                                        });
                                        //Navigator.pop(context);
                                        //_showSheet(type);
                                      });
                                }),
                          )
                        ])),
                  );
                });
            break;
        }
      }

      @override
      Widget build(BuildContext context) {
        return new Directionality(
            textDirection: TextDirection.rtl,
            child: new Scaffold(
              key: _scaffoldKeyExplore,
              appBar:
                  AppBar(title: Text("استكشاف"), elevation: 0.0, actions: <Widget>[
                IconButton(
                    icon: Icon(Icons.category, color: _primeColor),
                    onPressed: () => _showSheet("categories")),
                IconButton(
                    icon: Icon(Icons.filter_list, color: _primeColor),
                    onPressed: () => _showSheet("filters"))
              ]),
              body: Center(child: Text("Nothing..."));
            ));
      }
    }

谢谢

1 个答案:

答案 0 :(得分:0)

  

需要关闭模式并再次显示以应用更改

之所以会这样,是因为需要再次调用showModalBottomSheet的{​​{1}}来反映所做的更改。 在Flutter中,builder应当能够在状态改变的任何时间重建-此处不是这种情况,因为显示了底页。

我为什么会遇到此问题(在元级别上)?

将状态存储在StatefulWidget中对于保存UI状态很有用,但是如果要存储某些“应用程序状态”或“数据状态”,而该状态与屏幕所在的屏幕无关,则可以快速淘汰此技术。

现在是时候从根本上重新考虑您的状态管理,并采用一种成熟的状态管理模式,该模式将状态与小部件分离。幸运的是,有一些可供选择:

  • 将所有内容设置为全球化,就像您之前所做的那样。 这通常不是一个好主意,因为您违反了StatefulWidget的合同(可以在不通知小部件的情况下修改状态)。另外,您还会中断热重启以及类似的操作。
  • 使用 setState ,其中根窗口小部件下方的窗口小部件可以访问相同的状态。
  • 使用 InheritedWidget ,它是基于此的。
  • 使用臭名昭著的 BLoC模式,该模式也建立在ScopedModel的顶部,但是增加了一些InheritedWidget-y的东西,以使所有内容都变得更加被动。
  • 可能更多。

这是一个很棒的Youtube video about state management from Google I/O,其中展示了几种模式。

无论如何,底页是正确的摆设吗?

根据the Material Design spec,模态底页是“内联菜单或移动设备上简单对话框的替代方案,为其他项目,较长的描述和图示提供了空间”。

更具体地讲,Stream函数旨在显示一个随时间变化不会影响父级的小部件,而是(如果有的话)在单个时间点上影响小部件。这就是为什么它返回showModalBottomSheet而不是Future<T>的原因。

请注意,您正在尝试以不希望使用的方式使用底部纸。 对于您的情况,建议您仅使用一个新屏幕。