先看效果:
在推酷安卓客户端看到的这种效果,发现iOS端没有这种点击的动效,就随手研究了下。
分为三种效果:
- 单击
- 单击长按并滑动手指
- 单击长按滑动tableview
思路
思路一:
过程
在tableviewcell的contentview里面添加两个手势,一个UITapGestureRecognizer
和一个UILongPressGestureRecognizer
来获取当前点击是单击还是长按操作,方便的是如果是长按操作,那么在一个方法里面就可以捕捉整个长按的过程:
/**
* 处理长按手势
*
* @param longPressGestureRecognizer 长按手势
*/
- (void)handleLongPressGestures:(UILongPressGestureRecognizer *)longPressGestureRecognizer
{
if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan) {
//长按开始.......
//开始慢速动画
}
if((longPressGestureRecognizer.state == UIGestureRecognizerStateEnded || longPressGestureRecognizer.state == UIGestureRecognizerStateCancelled))
{
//长按结束和取消.....
//如果动画结束,直接移除layer
//如果动画没有结束,继续加速动画
}
if (longPressGestureRecognizer.state == UIGestureRecognizerStateChanged) {
//长按状态改变,手指滑动.....
//用[longPressGestureRecognizer locationInView:self]返回的CGPoint判断手指是在移到cell外部,加速动画至结束后移除
}
这里配合着给layer添加的animation的delegate使用,来判断动画是否在进行或者结束。
问题:
我先是在view上做效果,效果完成后改用自定义的cell调试,这时候发现了问题:
使用了自定义cell的tableview的didSelectRowAtIndexPath
这个代理方法不会调用。研究发现原来是我添加的两个手势和系统的select手势操作发生了冲突。导致那两个手势把系统手势拦截了下来,该方法不执行。那么该怎么解决这个问题呢?
我发现了这个方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//假如自定义添加了两个手势,那么该方法会调用三次,其中包括一次系统手势
//gestureRecognizer 返回的手势
// touch 接受的touch点击
//返回值代表是否拦截事件
}
在这个方法里面就可以做判断,如果是系统手势,就不拦截。如果是自定义手势,则拦截。
思路二:
过程
利用系统提供的touchesBegan
,touchesMoved
,touchesEnded
,touchesCancelled
四个方法进行逻辑判断提供动画效果。
因为我要在touchesBegan
这个方法里面判断是单击还是长按,来分别做快速和慢速动画,所以这里用了个小技巧,就是用延迟0.1秒
和touchCancelledOrEnded
做动画。
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
_touchCancelledOrEnded = NO;
excute_block_after(0.1f, ^{
[self creatAnimation];
});
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
_touchCancelledOrEnded = YES;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
_touchCancelledOrEnded = YES;
}
- (void)creatAnimation
{
if(_touchCancelledOrEnded == YES)
{
//快速动画
}else
{
//快速动画
}
}
具体过程请看代码。
待解决的问题
事实上,这个效果目前还不够完善。比如说在didSelectRowAtIndexPath
这个tableview代理里面填写代码在点击cell的时候跳转到另一个控制器。上面的演示demo也可以看出,单击的时候由于控制器之间的跳转太快,导致阴影动画看不清楚。最理想的状态是:在自定义cell内部拦截这个select事件,等到cell的动画结束后,再通知tableview的didSelectRowAtIndexPath
方法执行响应的控制器跳转代码。为了方便其他人使用,我应该在cell内部完成整个拦截和通知过程。
我曾在stackoverflow上查找相关问题无果后,问了这个问题,希望有人知道的话,能给我一个思路,我将非常感激您并完善它。
GitHub地址:点击这里
网友评论