iOS 为移动动画中的View添加touch事件

简介: 对Core Animation来说,不管是显式动画还是隐式动画,对其设置frame都是立即设置的,比如说给一个UIView做移动动画,虽然看起来frame在持续改变,但其实它的frame已经是最终值了,这种情况下,哪怕这个UIView是UIButton的实例,其触发touch事件的范围还是最终frame的地方。
对Core Animation来说,不管是显式动画还是隐式动画,对其设置frame都是立即设置的,比如说给一个UIView做移动动画,虽然看起来frame在持续改变,但其实它的frame已经是最终值了,这种情况下,哪怕这个UIView是UIButton的实例,其触发touch事件的范围还是最终frame的地方。比如一个Button的frame是(0,0,100,100),要把它从0,0移动到200,200,在这种情况下:
  1. 如果你使用的是显式动画(CAKeyframeAnimation和CABasicAnimation),是通过指定path或values来进行动画的,它的frame并没有改变,touch范围还是(0,0,100,100)这个范围内
  2. 如果你使用的是隐式动画(UIView的animate方法),是通过设置frame来进行动画的,那么它的touch范围就是(200,200,100,100)这个范围内
这个区别很重要,你只用记住,如果是用UIView做动画,设置的frame是有效的;
如果CALaye做动画设置的frame是无效的,你应该在动画结束后显式地指定position的值

如果我们要为移动动画中的View添加touch事件,就需要在后面用到hitTest。我们先创建一个动画Layer:
CGSize layerSize = CGSizeMake(100, 100);
CALayer *movingLayer = [CALayer layer];
movingLayer.bounds = CGRectMake(0, 0, layerSize.width, layerSize.height);
[movingLayer setBackgroundColor:[UIColor orangeColor].CGColor];
movingLayer.anchorPoint = CGPointMake(0, 0);
[self.view.layer addSublayer:movingLayer];
self.movingLayer = movingLayer;
这里面只有anchorPoint重要一些,因为anchorPoint能影响position的取值,对Layer来说,frame是抽象的,只有bounds和position是真实存在的,并且设置frame和设置anchorPoint的顺序不同,开始看到的结果也不同:

左边是先设置的anchorPoint再设置frame,右边是相反,可以看到如果是先设置anchorPoint的话,在刚开始就能得到正确的结果,即position为0,0。但如果是设置bounds的话就不用这么麻烦了,顺序无所谓。我在这里之所以要设置anchorPoint,是因为在后面的CAKeyframeAnimation将用position来做动画,如果anchorPoint为默认值(即0.5,0.5)的话,在动画中将会出现一个x、y轴一半的偏移,就像这样:

下面用一张图解释anchorPoint的取值:

position是以anchorPoint为原点的,默认这个原点在中心位置,自然就会出现上图x、y轴的偏移,其实只要我在动画中将position做个偏移就不用设置anchorPoint,但是我觉得动画从0到终点更直观一些,所以这才是我设置anchorPoint的原因,并不是说非设不可。最后用一个weak属性引用动画Layer并把这个Layer添加到self.view.layer中。
接下来是动画部分:
CAKeyframeAnimation *moveLayerAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//moveLayerAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
//moveLayerAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(320 - self.movingLayer.bounds.size.width, 0)];
moveLayerAnimation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],
                              [NSValue valueWithCGPoint:CGPointMake(320 - self.movingLayer.bounds.size.width, 0)]];
moveLayerAnimation.duration = 2.0;
moveLayerAnimation.autoreverses = YES;
moveLayerAnimation.repeatCount = INFINITY;
moveLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[self.movingLayer addAnimation:moveLayerAnimation forKey:@"move"];
如果是用CABasicAnimation做动画,则用fromValue及toValue替换setValues,timingFunction直接用线性,不用做其他变换,关于这个属性的预置值,我在 另一篇博文中有提到。
接下来为self.view添加手势识别:
........
    self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];
    [self.view addGestureRecognizer:self.tapGesture];
}

-(void)click:(UITapGestureRecognizer *)tapGesture {
    CGPoint touchPoint = [tapGesture locationInView:self.view];
    if ([self.movingLayer.presentationLayer hitTest:touchPoint]) {
        NSLog(@"presentationLayer");
    }
}
我在最开始的时候有提到,动画的过程只是看起来是动态变换的,其内部的值已经是固定的了。
简单说下Core Animation,Core Animation用三个Tree来完成动画:
  • Layer Tree
  • Presentation Tree
  • Render Tree
Layer Tree用来存储Layer最终的值,即不考虑动画的发生,你只要对一个Layer进行了一些诸如backgroundColor、position、alpha之类的赋值,其Layer Tree中存储的值立刻改变; Presentation Tree用来存储所有的要在动画过程中显示的值,与Layer Tree相反; Render Tree专门用来渲染Presentation Tree中的值,也是与Core Animation交互的唯一纽带,这一过程被系统隐藏了,我们不用管也没办法管。
这就是说Layer Tree与Presentation Tree其实都相当于是 模型对象,只存储Layer的状态,当我们要读取动画进行中的状态的时候,调用layer的presentationLayer属性就可以了,这个属性从Presentation Tree中返回代表当前动画状态的Layer,接下来调用Layer的hitTest方法就能判断是不是一次有效点击了。

目录
相关文章
|
6月前
|
API 定位技术 iOS开发
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
90 2
|
iOS开发
iOS 动画绘制圆形
iOS 动画绘制圆形
78 1
|
编译器 iOS开发 异构计算
读iOS核心动画笔记
读iOS核心动画笔记
53 0
|
7天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
【10月更文挑战第18天】本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户按下按钮时,按钮将从圆形变为椭圆形并从蓝色渐变为绿色;释放按钮时,动画恢复原状。通过UIView的动画方法和弹簧动画效果,实现平滑自然的动画过渡。
28 5
|
2月前
|
Swift iOS开发 UED
揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【9月更文挑战第5天】本文通过具体案例介绍如何在iOS应用中使用Swift与UIKit实现自定义按钮动画,当用户点击按钮时,按钮将从圆形变为椭圆形并从蓝色渐变到绿色,释放后恢复原状。文中详细展示了代码实现过程及动画平滑过渡的技巧,帮助读者提升应用的视觉体验与特色。
53 11
|
3月前
|
Swift iOS开发 UED
【绝妙创意】颠覆你的视觉体验!揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【8月更文挑战第13天】本文通过一个具体案例,介绍如何使用Swift与UIKit在iOS应用中创建独特的按钮动画效果。当按钮被按下时,其形状从圆形变化为椭圆形,颜色则从蓝色渐变为绿色;释放后,动画反向恢复原状。利用UIView动画方法及弹簧动画效果,实现了平滑自然的过渡。通过调整参数,开发者可以进一步优化动画体验,增强应用的互动性和视觉吸引力。
48 7
|
6月前
|
API 定位技术 iOS开发
IOS开发基础知识:什么是 Cocoa Touch?它在 iOS 开发中的作用是什么?
【4月更文挑战第18天】**Cocoa Touch** 是iOS和Mac OS X应用的核心框架,包含面向对象库、运行时系统和触摸优化工具。它提供Mac验证的开发模式,强调触控接口和性能,涵盖3D图形、音频、网络及设备访问API,如相机和GPS。是构建高效iOS应用的基础,对开发者至关重要。
65 0
|
iOS开发
iOS 常用阅读软件打开书籍的转场动画
iOS 常用阅读软件打开书籍的转场动画
92 0
|
6月前
|
iOS开发
iOS设备功能和框架: 如何使用 Core Animation 创建动画效果?
iOS设备功能和框架: 如何使用 Core Animation 创建动画效果?
135 0
|
API iOS开发
iOS 自定义转场动画 UIViewControllerTransitioning
iOS 自定义转场动画 UIViewControllerTransitioning
87 0