iOS7 应用管理器中的 UICollectionView “滑动”?
Posted
技术标签:
【中文标题】iOS7 应用管理器中的 UICollectionView “滑动”?【英文标题】:The UICollectionView "swipe-away" in iOS7 app manager? 【发布时间】:2014-04-11 09:35:38 【问题描述】:在任何 2014 年以上的 iPhone 或 iPad 上,双击主页按钮以查看“应用管理器”
这是一个左右 UICollectionView 但它有一个“滑动”手势..向上滑动。它是如何完成的?从 UICollectionView 中“移除”一个单元格并不容易。
googlers 的脚注 .. 对于“剥离”、“撕掉”、集合视图中的一个单元格的一般问题,这里有一个完整的解释:https://***.com/a/24339705/294884希望它对某人有所帮助。
【问题讨论】:
在内部,这不是一个集合视图。它是一系列滚动视图,由控制器管理。事实上,我正在做类似的事情,但还没有什么要宣布的。 Ahhh ...**这是一系列滚动视图,由控制器管理** Leo 典型的令人难以置信的洞察力! :O Joe,您可以将调试器附加到模拟器上的 SpringBoard 并检查视图层次结构。 嗯 .. 这就是你说的那些听起来很容易的事情之一 :) 谢谢,尽管我会深入研究这一点!您能否将最后一条评论作为答案,因为它非常有用??? 让我看看能不能及时拿出真正的解决方案。 【参考方案1】:这可能比您问题中的 cmets 建议的要简单得多。
您的单元格应该包含一个视图(您要拖出的东西),并且您向该视图添加一个 UIPanGestureRecognizer。
在手势的操作方法中,您向上或向下移动视图,当它离得太远以至于您想要删除它时,您只需将其动画化即可。这里有很多关于这部分的问题。
这会在您的收藏中留下空白,现在您需要四处移动。事实证明这很简单:
[_collectionView performBatchUpdates:^
[_collectionView deleteItemsAtIndexPaths:@[indexPath]];
completion:^(BOOL finished)
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
];
删除单元格右侧的东西滑过,我们都很好。
另一个需要克服的问题:确保您的手势识别器和集合视图能够很好地配合使用。值得庆幸的是,这也不是太棘手。
[_collectionView.panGestureRecognizer requireGestureRecognizerToFail:pgr]; //where pgr is the recognizer you made for dragging the view off
这意味着为了让集合视图的平移手势发挥作用,你的手势必须失败。因此,您需要进行设置,使其仅在上下平移时起作用,并让集合视图仍然为从左到右的平移执行其操作。在您的手势识别器的委托中,实现以下方法,该方法仅检查您是在 x 轴还是 y 轴上移动更多。
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
CGPoint translation =[gestureRecognizer translationInView:self.view];
return(translation.x * translation.x > translation.y * translation.y);
【讨论】:
当我使用这种方法时,我使用的集合视图占据了整个屏幕大小,但我希望你可以告诉集合视图不要剪辑,它不会。我会测试一下,稍后再报告。 没有问题,只是通过取消选中情节提要中单元格的“剪辑子视图”来尝试一下,然后就可以了。 您也可以在视图层上将masksToBounds
设置为YES
,如果您以编程方式进行而不使用故事板。当我实现一个集合视图时,我自己做了这个,我必须将项目从 cv 拖到另一个视图的顶部。如果需要,您可以从 performBatchUpdates:completion:
制作动画,这毫无价值。【参考方案2】:
我一直在寻找这个功能并使用@mbehan 的建议,我使用 UICollectionView 伪造了这个功能。
我所做的是我在集合单元格(透明背景)上添加了一个较小尺寸的视图,并在 CollectionView 上添加了一个平移手势(不是在每个单元格上),然后在平移手势上我移动视图,它看起来像单元格正在移动。视图到达某个点后,我首先将其隐藏,然后删除集合视图单元格。
单元层次结构:collectionViewCell -> 视图(标签值==2)-> UILabel(标签值== 1) 标签仅用于占位符目的。
我在下面发布我的代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cards" forIndexPath:indexPath];
UILabel *lblNumber = (UILabel*)[cell.contentView viewWithTag:1];
UIView *viewTouch = (UIView*)[cell.contentView viewWithTag:2];
[viewTouch setHidden:NO];
[lblNumber setText:arrCards[indexPath.row]];
return cell;
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
return UIEdgeInsetsMake(0, 50, 0, 30);
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
if([gestureRecognizer isEqual:panGesture])
CGPoint point = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:collectionView_];
if(point.x != 0) //adjust this condition if you want some leniency on the X axis
//The translation was on the X axis, i.e. right/left,
//so this gesture recognizer shouldn't do anything about it
return NO;
return YES;
- (IBAction)panGestureCalled:(UIPanGestureRecognizer *)sender
yFromCenter = [sender translationInView:collectionView_].y; //%%% positive for up, negative for down
UIView *view = sender.view;
CGPoint location = [view.superview convertPoint:view.center toView:collectionView_];
NSIndexPath *indexPath = [collectionView_ indexPathForItemAtPoint:location];
UICollectionViewCell *cell = [collectionView_ cellForItemAtIndexPath:indexPath];
UIView *touchView = (UIView*)[cell.contentView viewWithTag:2];
switch (sender.state)
case UIGestureRecognizerStateBegan:
originalPoint = touchView.center;
break;
;
case UIGestureRecognizerStateChanged:
touchView.center = CGPointMake(originalPoint.x , originalPoint.y + yFromCenter);
break;
;
//%%% let go of the card
case UIGestureRecognizerStateEnded:
CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:collectionView_].y);
if (velocityY < -30 && yFromCenter<0)
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
else if ((yFromCenter< 0 && yFromCenter > -200) || yFromCenter > 0)
CGFloat animationDuration = (ABS(velocityY)*.0002)+.2;
[self resettleViewToOriginalPosition:touchView andDuration:animationDuration];
else
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
;
break;
case UIGestureRecognizerStatePossible:break;
case UIGestureRecognizerStateCancelled:break;
case UIGestureRecognizerStateFailed:break;
-(void)resettleViewToOriginalPosition:(UIView*)view andDuration:(float)duration
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
[view setCenter:originalPoint];
completion:^(BOOL finished)
];
- (void)hideView:(UIView*)view withDuration:(float)duration andIndexPath:(NSIndexPath*)indexPath
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
CGRect frame = view.frame;
frame.origin.y = -300;
view.frame = frame;
completion:^(BOOL finished)
[view setHidden:YES];
CGRect frame = view.frame;
frame.origin.y = 39;
view.frame = frame;
NSLog(@"View is hidden.");
[arrCards removeObjectAtIndex:indexPath.row];
[collectionView_ performBatchUpdates:^
[collectionView_ deleteItemsAtIndexPaths:@[indexPath]];
completion:^(BOOL finished)
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
];
];
并将 CollectionView 的 pagingEnabled 保持为 NO,然后就可以了。
【讨论】:
以上是关于iOS7 应用管理器中的 UICollectionView “滑动”?的主要内容,如果未能解决你的问题,请参考以下文章