Flutter-多选ListView

时间:2018-11-08 15:25:53

标签: android ios dart flutter

在我的应用中,我确实有一个列表,在该列表上已经实现了长按选择的this post of Raouf Rahiche。启用选择后,我确实有一个不同的appbar,上面有一个IconButton,应该禁用选择。但是我不知道该怎么做。

到现在,它还没有按照应有的方式工作。该行为显示在下面的视频中。 enter image description here

longpress-selection是一个StatefulWidget:

class _SelectableItems extends State<SelectableItems> {
  bool isSelected = false;
  GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();

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

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
        onLongPress: () {
          setState(() {
            isSelected = !isSelected;
          });
          widget.callback();
        },
        onTap: () {
          setState(() {
            isSelected = !isSelected;
          });
          if (widget.longPressEnabled) {
            widget.callback();
          } else {
            Navigator.push(
              context, 
              MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
            );
          }
        },
        child: ListTile(
          leading: CircleAvatar(
            child: (isSelected
              ? Icon(
                Icons.check,
                color: Colors.white,
              )
              : (widget.image != "no image"
                ? Container(
                  width: 40.0,
                  height: 40.0,
                  decoration: new BoxDecoration(
                    image: new DecorationImage(
                      colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
                      image: AssetImage(widget.image),
                      fit: BoxFit.cover,
                    ),
                    borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
                  ),
                )
                : Text(
                  widget.name[0].toUpperCase(),
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 21.0,
                    fontWeight: FontWeight.w400
                  ),
                )
              )
            ),
            backgroundColor: (isSelected
              ? googleMaterialColors.primaryColor()
              : widget.color.withOpacity(1.00)
            )
          ),
          title: Padding(
            padding: EdgeInsets.only(top: 25.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                widget.title
              ],
            ),
          ),
        ),
      );
  }
}

我在SideHeaderListView内这样调用此小部件:

bool longPressFlag = false;
List<String> indexList = new List();
//other code

                return SideHeaderListView(                  
                    hasSameHeader: (int a, int b){
                      return snapshot.data[a].name[0] == snapshot.data[b].name[0];                  
                    },
                    itemCount: snapshot.data.length,
                    headerBuilder: (BuildContext context, int index){
                      return new Padding(
                        padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
                        child: Container(
                          width: 10.0,
                          child: Text(
                            snapshot.data[index].name[0].toUpperCase(),
                            style: TextStyle(
                              color: googleMaterialColors.primaryColor().withGreen(120),                        
                              fontFamily: "Google-Sans",
                              fontSize: 15.0,
                              fontWeight: FontWeight.w600
                            ),
                          ),
                        ),
                      );
                    },
                    itemExtend: 70.0,
                    itemBuilder: (BuildContext context, int index){

                      Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);                    
                      String image = snapshot.data[index].image;


                      return SelectableItems(
                        color: usedColor,
                        name: snapshot.data[index].name,
                        title: (searchController.text.isEmpty
                          ? Text(snapshot.data[index].name)
                          : recipeName(searchCondition, snapshot.data[index].name)
                        ),
                        index: index,
                        image: image,
                        longPressEnabled: longPressFlag,
                        //isSelected: selectedFlag,
                        callback: () {
                          if (indexList.contains(snapshot.data[index].name)) {
                            indexList.remove(snapshot.data[index].name);
                          } else {
                            indexList.add(snapshot.data[index].name);
                          }
                          longPress();
                        },
                      );
                    },
                  );

void longPress() {
    setState(() {
      if (indexList.length == 0) {
        longPressFlag = false;
      } else {
        longPressFlag = true;
      }
    });
  }

我希望有人能够解决我的问题。预先感谢。

2 个答案:

答案 0 :(得分:0)

第一件事是,您应该像这样在构造函数中为每个项目添加一个键:

MyItem({Key key}): super(key: key);

为什么要钥匙? 按键可让您正确识别小部件。 参见文档:

  

新的窗口小部件将仅用于更新现有元素,如果其   键与与该控件关联的当前窗口小部件的键相同   元件。

创建一个GlobalKey(一个GLobal键扩展了Key) 对于从中访问小部件的每个项目,请创建一个全局密钥。 从文档中:

  

整个应用程序中唯一的键。全局密钥唯一   识别元素。全局键提供对其他对象的访问,   与元素相关联,例如[BuildContext]和   [StatefulWidget] s,一个[State]。

在代码中为每个项目(在您的SelectableItem中为您)创建一个全局密钥:

...
var key = new GlobalKey<SelectableItem >();
this.items.put(position, key);
return new SelectableItem(key: key,...);

Items是一张地图,您可以在其中保存位置和全局密钥。 现在,当您想从父级中选择一个视图时,只需从项目地图中访问globalKey并访问该小部件即可执行您想要的操作(更新,取消选中等...)

编辑:例如:

class SideHeaderListView  {

  Map<int, GlobalKey<_SelectableItems>> map = new Map();

  create() {
    for (int i = 0; i< 10; i++) {
      var key = new GlobalKey<_SelectableItems>();
      var item = new SelectableItems(key: key);
      map.putIfAbsent(i, () => key);
    }
  }

  redrawItem(int i) {
    var widget = this.map[i].currentState;
    widget.redraw();
  }
}

class SelectableItems extends StatefulWidget {

  SelectableItems({key: Key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return new _SelectableItems();
  }
}

class _SelectableItems extends State<SelectableItems> {

  @override
  Widget build(BuildContext context) {
    return new Text("test");
  }

  redraw() {
    setState(() {

    });
  }

 }

答案 1 :(得分:0)

您已注释了部分代码-//isSelected: selectedFlag, 我认为,您必须将此字段添加到小部件中

class SelectableItems extands StatefulWidget {
    SelectableItems({this.isSelected = false});
    final bool isSelected;
    ...

class _SelectableItems extends State<SelectableItems> {
  bool isSelected;

  @override
  void initState() {
    isSelected = widget.isSelected ?? false;
    super.initState();
  }
  ....

在创建项目列表时:

return SelectableItems(
  ...
  isSelected: indexList.contains(snapshot.data[index].name)

我认为这可能有效