You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中GridView多选时首个选中项不显示高亮状态求助

Flutter GridView 多选首个组件无高亮问题解决

问题现象

使用GridView.count实现组件多选时,首个选中的组件已被加入选中列表,但无法显示高亮效果(图标未变色、文字样式未变更)。当前已选中4个组件,仅首个选中项无视觉反馈。

问题原因

Dart中默认的contains方法通过对象引用判断是否相等,而从JSON解析生成的CommodityModel实例,即使属性完全一致,也是不同的对象引用。当首次选中某个组件后,后续判断selectedItems.contains(order)时,会因为引用不匹配返回false,导致高亮逻辑不生效。

解决方案

方案1:重写CommodityModel的==运算符和hashCode

基于唯一标识(比如commodityID)定义对象相等性,从模型层统一解决问题:

class CommodityModel {
  String? commodityID;
  String? commodityName;
  String? commodityImage;

  CommodityModel({
    this.commodityID,
    this.commodityName,
    this.commodityImage,
  });

  CommodityModel.fromJson(Map<String, dynamic> json) {
    commodityID = json['commodityID'];
    commodityName = json['commodityName'];
    commodityImage = json['commodityImage'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['commodityID'] = commodityID;
    data['commodityName'] = commodityName;
    data['commodityImage'] = commodityImage;
    return data;
  }

  // 基于commodityID判断对象相等
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is CommodityModel &&
          runtimeType == other.runtimeType &&
          commodityID == other.commodityID;

  // 配合==生成对应的hashCode
  @override
  int get hashCode => commodityID.hashCode;
}

方案2:替换contains为基于唯一ID的判断

如果不想修改模型类,可以在判断选中状态时,用any方法通过commodityID匹配:

Expanded(
  child: Padding(
    padding: const EdgeInsets.all(8.0),
    child: GridView.count(
      crossAxisCount: 2,
      crossAxisSpacing: 10,
      mainAxisSpacing: 10,
      shrinkWrap: true,
      children: cC.allCommodityList.map((order) {
        // 用唯一ID判断是否选中
        final isSelected = selectedItems.any((item) => item.commodityID == order.commodityID);
        return InkWell(
          onTap: () {
            setState(() {
              final exists = selectedItems.any((item) => item.commodityID == order.commodityID);
              exists 
                  ? selectedItems.removeWhere((item) => item.commodityID == order.commodityID) 
                  : selectedItems.add(order);
              commodityName = order.commodityName;
              commodityid = order.commodityID;
            });
          },
          child: Card(
            child: Column(
              children: [
                Expanded(
                  child: isSelected
                      ? SvgPicture.asset(
                          'assets/toiletpaper.svg',
                          color: Color.fromRGBO(0, 76, 32, 1),
                        )
                      : SvgPicture.asset('assets/toiletpaper.svg'),
                ),
                isSelected
                    ? TopBorderNoTap(
                        listColor: [
                          Color.fromRGBO(229, 229, 229, 1),
                          Color.fromRGBO(0, 76, 32, 1),
                        ],
                        text: order.commodityName.toString(),
                        color: Colors.white,
                        textColor: Colors.white)
                    : TopBorderNoTap(
                        listColor: [
                          Color.fromRGBO(229, 229, 229, 1),
                          Colors.white
                        ],
                        text: order.commodityName.toString(),
                        textColor: Colors.black,
                      )
              ],
            ),
          ),
        );
      }).toList(),
    ),
  ),
)

说明

两种方案都能解决问题,推荐方案1,因为它从模型层统一了对象相等性判断,后续其他业务场景也能复用,避免重复编写判断逻辑。

内容的提问来源于stack exchange,提问作者wuuyungwuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:36:30