最近踩到一个坑,表现状况如下:
UICollectionView的Cell中有一个UIImageView,有选中和未选中两个状态。在某种条件下点击时是不做任何改变的(即保持未选中状态)。
起初的做法是:
将UIImageView的 image
/ hightedImage
属性和cell的选中/未选中状态进行绑定,通过UIImageView的 setHighlighted:
方法来切换选中状态。
// MyController.m - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (conditionAIsSatisfied) { ...... } } // MyCollectionViewCell.m - (void)updateCellWithSelected:(BOOL)selected { [_imgView setHighlighted:selected]; }
存在的问题是:
在UICollectionView的 didSelectItemAtIndexPath:
方法中,即使不执行if语句中的更新imageView的方法, _imgView
也会更新为选中状态的图片。而collectionViewCell中的 updateCellWithSelected:
也是没有执行的。那么,为什么 _imgView
的图片会更新呢?
类似的,在UITableView中做同样的控制,UITableViewCell中 _imgView
的图片为什么就不会改变呢?
UICollectionViewDelegate
中相关的各个回调方法如下。
// Methods for notification of selection/deselection and highlight/unhighlight events.
// The sequence of calls leading to selection from a user touch is:
//
// (when the touch begins)
// 1. -collectionView:shouldHighlightItemAtIndexPath:
// 2. -collectionView:didHighlightItemAtIndexPath:
//
// (when the touch lifts)
// 3. -collectionView:shouldSelectItemAtIndexPath: or -collectionView:shouldDeselectItemAtIndexPath:
// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:
// 5. -collectionView:didUnhighlightItemAtIndexPath:
UICollectionViewCell并没有像UITableViewCell一样提供类似 selectionStyle
的属性来直接将选中时的样式设置为 UITableViewCellSelectionStyleNone
,而是给了开发者更多的灵活性,提供了更多的代理方法。通过查看 UICollectionViewDelegate
以及在 shouldSelectItemAtIndexPath:
和 didHighlightItemAtIndexPath:
等函数中打断点逐个排查,发现cell的highlighted和imageview的highlighted是关联的。当cell被选中时,虽然 didSelectItemAtIndexPath:
方法并没有执行实质性的代码,但在其之前执行的 shouldHighlightItemAtIndexPath:
方法默认为 YES
,使整个cell的状态为highlighted,相应的imageView的状态就是显示highlighted的图片了。
知道了原因之后,总结了两个解决方案:
1.添加 shouldSelectItemAtIndexPath:
方法,在其中增加 conditionAIsSatisfied
的判断,来对应地返回 YES
或 NO
。
2.在 MyCollectionViewCell
中,不再为UIImageView的 image
/ hightedImage
设置不同的图片,而是设置为同一个图片。然后在 -updateCellWithSelected:
中根据 selected
值来替换选中/未选中的图片。
对比来看,1的缺点在于,已选中的cell无法取消选中。2的缺点在于,切换图片时会有点突兀。
综合考量,我最后选择了方案2。
但是,上面啰嗦了半天,其实只需要一句代码解决问题:
collectionView.allowSelection = NO;
来自 这里 。UITableView同理。
果然是简洁至上。