objective-c - Obj-c - 使用 PanGesture 突出显示 UICollectionViewCells?
问题描述
当用户将手指拖到单元格上时,我正在使用下面的代码来跟踪单元格(这很好用)。也就是说,当用户将手指拖到它们上方时,我想突出显示每个单元格(或更改自定义单元格中背景视图的颜色)。我怎样才能做到这一点?见下文。
视图控制器.m
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
[self.ringCollectionView addGestureRecognizer:panGesture];
}
- (void) handlePanGesture:(UIPanGestureRecognizer*) panGesture{
CGPoint location = [panGesture locationInView:self.ringCollectionView];
NSIndexPath *indexPath = [self.ringCollectionView indexPathForItemAtPoint:location];
NSMutableArray *selectedIndexes = [NSMutableArray arrayWithArray:[self.ringCollectionView indexPathsForSelectedItems]];
if (![selectedIndexes containsObject:@(indexPath.row)]){
NSLog(@"THIS CELL IS %ld", (long)indexPath.row);
}
else if (panGesture.state == UIGestureRecognizerStateEnded){
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 10;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"RingCollectionViewCell";
RingCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Tapping");
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(118, 118);
}
解决方案
我最初的答案是无关紧要的,因为我一开始并不了解想要的结果,所以我完全删除了它。这是更新的一个:
首先,我相信通过“本机”机制跟踪选定的单元格UICollectionView
是合理且一致的,不需要在单元格内使用自定义手势处理程序。但是,为了表示选定状态,您需要设置selectedBackgroundView
属性,如下所示:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"RingCollectionViewCell" forIndexPath:indexPath];
if (!cell.selectedBackgroundView) {
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
cell.selectedBackgroundView.backgroundColor = [UIColor grayColor];
}
return cell;
}
我不知道您的RingCollectionViewCell
课程是如何设计的,但请注意,您需要确保contentView
此单元格具有透明的背景颜色,否则它将遮盖selectedBackgroundView
.
现在是棘手的部分。UIPanGestureRecognizer
非常快速地获取事件,并且当用户只是将手指保持在屏幕上时,将经常调用句柄方法,因此您需要以某种方式抑制不应切换单元格选定状态的事件。我的建议是,如果它们发生在同一个单元格中,则忽略所有后果事件。为了实现这样的行为,我们需要存储最后一个单元格的索引路径,让我们使用一个简单的属性:
@interface ViewController ()
@property (strong, nonatomic, nullable) NSIndexPath *trackingCellIndexPath;
@end
现在您需要在手势句柄方法中将最后触摸单元格的索引路径分配给此属性。您还需要在手势完成或取消时重置此属性,如果给定索引路径不等于跟踪的索引路径,则切换选择,否则忽略触摸事件:
- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
// Reset the tracking state when the gesture is finished
switch (recognizer.state) {
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
self.trackingCellIndexPath = nil;
return;
default:
break;
}
// Obtain the cell the user is currently dragging over
CGPoint location = [recognizer locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
// If the user currently doesn't touch any cell, reset the tracking state and prepare to listen to another cell
if (!indexPath) {
if (self.trackingCellIndexPath) {
self.trackingCellIndexPath = nil;
}
return;
}
// If current event is subsequent gesture event which happens within the same cell, ignore it
if (self.trackingCellIndexPath == indexPath) {
return;
}
// If the cell hasn't been previously tracked, switch the selected state and start tracking it
self.trackingCellIndexPath = indexPath;
if ([self.collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
[self.collectionView deselectItemAtIndexPath:indexPath animated:YES];
} else {
[self.collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
}
}
最后要更改的是集合视图的选择模式。正如您期望多个单元格保持选中状态一样,只需在以下位置切换allowsMultipleSelection
您的集合视图viewDidLoad
:
- (void)viewDidLoad {
...
self.collectionView.allowsMultipleSelection = YES;
}
推荐阅读
- java - 有没有办法从 JAVA 的浏览器中获取所有打开的 URL?
- docker - Spark on Kubernetes : /opt/entrypoint.sh: /sbin/tini: No such file or directory 错误
- python-3.x - Python中Selenium webdriver中元素的条件选择
- java - 如果我运行我的数组程序,0 会显示我如何删除它?
- google-data-studio - 我可以使用数据工作室 API 从报告中提取数据吗?
- php - 使用 PHP 在 FPDF 中的单元格中自动换行?
- swift - snapkit 登录工具包不工作 Swift Xcode 11.3.1
- java - 在获取特定数据集的 BQ 表列表时获取 AppIdentityServiceFailureException getAccessToken
- reactjs - 在反应中获取 url 作为对象
- python - Chart.js 不显示 Django Rest API 数据