Light
Light
目录
  1. 先看效果:
  2. 思路
    1. 思路一:
      1. 过程
      2. 问题:
    2. 思路二:
      1. 过程
  3. 待解决的问题

一个波纹阴影点击和长按效果的TableViewCell

在推酷安卓客户端看到的这种效果,发现iOS端没有这种点击的动效,就随手研究了下。

先看效果:

分为三种效果:

  • 单击
  • 单击长按并滑动手指
  • 单击长按滑动tableview

demo

思路

思路一:

过程

在tableviewcell的contentview里面添加两个手势,一个UITapGestureRecognizer和一个UILongPressGestureRecognizer来获取当前点击是单击还是长按操作,方便的是如果是长按操作,那么在一个方法里面就可以捕捉整个长按的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 处理长按手势
*
* @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手势操作发生了冲突。导致那两个手势把系统手势拦截了下来,该方法不执行。那么该怎么解决这个问题呢?
我发现了这个方法:

1
2
3
4
5
6
7
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//假如自定义添加了两个手势,那么该方法会调用三次,其中包括一次系统手势
//gestureRecognizer 返回的手势
// touch 接受的touch点击
//返回值代表是否拦截事件
}

在这个方法里面就可以做判断,如果是系统手势,就不拦截。如果是自定义手势,则拦截。

思路二:

过程

利用系统提供的touchesBegan,touchesMoved,touchesEnded,touchesCancelled四个方法进行逻辑判断提供动画效果。
因为我要在touchesBegan这个方法里面判断是单击还是长按,来分别做快速和慢速动画,所以这里用了个小技巧,就是用延迟0.1秒touchCancelledOrEnded做动画。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-(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地址:点击这里