如何在UICollectionViewListCell+UIListContentConfiguration中忽略配件视图点击
解决UICollectionViewListCell自定义配件视图的点击拦截问题
针对你遇到的自定义配件视图点击异常问题,这里提供两种实用解决方案:
方案一:通过CollectionView代理拦截高亮事件
利用UICollectionViewDelegate的shouldHighlightItemAt方法,判断触摸点是否落在配件视图区域,直接禁止该区域的高亮与选择触发。
- 实现代理方法:
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { guard let cell = collectionView.cellForItem(at: indexPath) as? UICollectionViewListCell, let touch = collectionView.touches(for: cell)?.first else { return true } let touchLocation = touch.location(in: cell) // 判断触摸点是否在尾部配件视图范围内 if let accessoryView = cell.trailingAccessoryView, accessoryView.frame.contains(touchLocation) { return false } return true }
- 完善正常点击逻辑:
在didSelectItemAt中处理数据更新、复选框状态同步,并实现短暂高亮效果:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { // 更新数据模型的选中状态 yourDataArray[indexPath.row].isSelected.toggle() // 刷新单元格,同步复选框显示 collectionView.reloadItems(at: [indexPath]) // 取消选中,实现点击后的短暂高亮 collectionView.deselectItem(at: indexPath, animated: true) }
方案二:自定义无交互的配件容器视图
通过自定义一个不响应触摸事件的容器视图包裹复选框,从根源上拦截触摸事件传递。
- 创建无交互容器视图:
class NonInteractiveAccessoryContainer: UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { // 返回nil表示不处理任何触摸事件,事件不会向下传递 return nil } }
- 在CellRegistration中使用该容器:
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, YourDataModel> { cell, indexPath, model in // 配置内容视图 var contentConfig = UIListContentConfiguration.valueCell() contentConfig.text = model.title cell.contentConfiguration = contentConfig // 配置复选框视图 let checkmarkImage = model.isSelected ? UIImage(systemName: "checkmark.square.fill") : UIImage(systemName: "square") let checkmarkView = UIImageView(image: checkmarkImage) checkmarkView.translatesAutoresizingMaskIntoConstraints = false // 使用自定义容器包裹复选框 let accessoryContainer = NonInteractiveAccessoryContainer() accessoryContainer.addSubview(checkmarkView) // 布局复选框 NSLayoutConstraint.activate([ checkmarkView.centerXAnchor.constraint(equalTo: accessoryContainer.centerXAnchor), checkmarkView.centerYAnchor.constraint(equalTo: accessoryContainer.centerYAnchor), checkmarkView.widthAnchor.constraint(equalToConstant: 24), checkmarkView.heightAnchor.constraint(equalToConstant: 24) ]) // 设置尾部配件 cell.trailingAccessory = UIAccessory.customView(configuration: .init(customView: accessoryContainer)) }
- 同样配合方案一中的
didSelectItemAt逻辑完成数据更新和高亮处理。
补充说明
直接设置imageView.isUserInteractionEnabled = false无效的原因是:UIAccessory.customView的系统容器视图仍会接收触摸事件,仅禁用子视图交互无法阻止容器将事件传递给单元格,因此需要从容器或代理层面拦截。
内容的提问来源于stack exchange,提问作者nayooti
相关产品推荐
相关产品推荐

