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
相关产品推荐
相关产品推荐

