android - Flutter - 多选 ListView

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

到目前为止,它还没有按应有的方式工作。该行为显示在下面的视频中。

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;
      }
    });
  }

我希望有人能够解决我的问题。提前致谢。

最佳答案

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

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

为什么是 key ? 一个键可让您正确识别您的小部件。 见文档:

A new widget will only be used to update an existing element if its key is the same as the key of the current widget associated with the element.

创建一个全局键(一个全局键扩展键) 对于要从​​中访问小部件的每个项目,创建一个全局键。 来自文档:

A key that is unique across the entire app. Global keys uniquely identify elements. Global keys provide access to other objects that are associated with elements, such as the a [BuildContext] and, for [StatefulWidget]s, a [State].

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

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

Items 是一个可以保存位置和全局键的 map 。 现在,当您想从父项中选择 View 时,只需从项目映射中访问 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(() {

    });
  }

 }

https://stackoverflow.com/questions/53210904/

相关文章:

dart - Flutter 有数据绑定(bind)吗?

ios - 如何在 Flutter 中隐藏导航栏(在 iPhone X 上)

flutter - 因为sdk的flutter_test的每个版本都依赖... sdk的flutte

android - 如何在没有 Android Studio 的情况下使用模拟器在 VS 代码中安装

flutter - 永久持久的 Bottom Sheet flutter

dart - Flutter 应用程序在启动时崩溃

firebase - Flutter:取消 Google 登录流程时出现平台异常

dart - 通过滑动更改路线

intellij-idea - 如何在 IntelliJ 中自动完成/导入 Flutter 类?

proxy - 企业防火墙后面的 Flutter 应用程序在获取包期间引发 TLS 错误