写在前面
collectionView的多选是个老生常谈的问题了,但是当首次实现的时候还是要注意点什么的。
实现多选
这俩属性控制这些items是否可以选择,如果是,是否可以同时选择多个。
// These properties control whether items can be selected, and if so, whether multiple items can be simultaneously selected.
@property (nonatomic) BOOL allowsSelection; // default is YES
@property (nonatomic) BOOL allowsMultipleSelection; // default is NO
只需要 allowsMultipleSelection = YES
你的collectionView就支持多选了。
你可能会问,我怎么没看到,看这里
collectionView有一个属性,保存着被选中item的indexPath
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedItems; // returns nil or an array of selected index paths
在这两个方法里面打印一下,就会看到,点击选中,点击取消选中,记录的一点都没错。-collectionView: didSelectItemAtIndexPath:
,
collectionView: didDeselectItemAtIndexPath:
那么怎么让他显示出来呢,接着去看UICollectionViewCell
的API,通过重写这两个方法,你不仅可以自定义selected的UI,还可以自定义highlighted的
// Cells become highlighted when the user touches them.
// The selected state is toggled when the user lifts up from a highlighted cell.
// Override these methods to provide custom UI for a selected or highlighted state.
// The collection view may call the setters inside an animation block.
@property (nonatomic, getter=isSelected) BOOL selected;
@property (nonatomic, getter=isHighlighted) BOOL highlighted;
要记得先调用父类的
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.backgroundColor = selected ? [UIColor yellowColor] : [UIColor cyanColor];
}
到此结束,你只需要做这么多。
全选,取消全选
这里用到了四个方法
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath; // called when the user taps on an already-selected item in multi-select mode
- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition;
- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
前两个根据自己的需要返回YES或NO,后面两个文档上有句话需要注意:
This method does not cause any selection-related delegate methods to be called.
意思说着两个方法不会导致任何选中,取消选中的代理方法被调用。刷新UI需要手动处理。
- (void)selectedAllorCancel:(UIBarButtonItem *)item {
if ([item.title isEqualToString:@"全选"]) {
[item setValue:@"取消" forKey:@"title"];
[self shouldSelectedAll:YES];
}else {
[item setValue:@"全选" forKey:@"title"];
[self shouldSelectedAll:NO];
}
}
- (void)shouldSelectedAll:(BOOL )selectedAll {
for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) {
if (selectedAll) {
if ([self collectionView:self.collectionView shouldSelectItemAtIndexPath:indexPath]) {
[self.collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
LCRegionCell *cell = (LCRegionCell*)[self.collectionView cellForItemAtIndexPath:indexPath];
cell.selected = YES;
}
}else {
if ([self collectionView:self.collectionView shouldDeselectItemAtIndexPath:indexPath]) {
[self.collectionView deselectItemAtIndexPath:indexPath animated:YES];
LCRegionCell *cell = (LCRegionCell*)[self.collectionView cellForItemAtIndexPath:indexPath];
cell.selected = NO;
}
}
}
}
之前看说要用到这个方法,实际操作不用也没什么区别,感觉这里并不需要,还望告知解惑。
- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion; // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
注意:为节省时间这里整个collectionView的所有item遍历的是collectionView.indexPathsForVisibleItems
,也就是说仅在当前屏幕上显示的item,项目根据需求去遍历
总结
总的来说collectionView很强大,可以这么说,凡是用tableView实现的用collectionView同样可以,支持的功能要比tableView要多。还有很多待发现的功能,api文档是最好的学习途径。