这个问题是在之前做项目的时候遇到的,今天就顺便总结并扩展一下,由于界面动画比较多,需要点击运动中的button,在网上找了很久也没找到合适的答案,最后在解决其他问题时发现此问题的解决方案,首先还是先说明下常用的动画:
- Core Animation动画实现位移效果
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 100, 50, 50);
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
//创建basic位移动画
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
//起点,fromValue是对象类型,所以CGPoint必须封装成对象
basicAnimation.fromValue = [NSValue valueWithCGPoint:button.center];
//到哪个点,记得移动的是视图的中心点
basicAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 550)];
//动画运行总时间
basicAnimation.duration = 3.0;
//重复次数
// basicAnimation.repeatCount = MAXFLOAT;
//是否倒退
// basicAnimation.autoreverses = YES;
//设置为线性移动
basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
//设置视图在动画结束后停留在结束位置,这两个代码同时设置才有效果
basicAnimation.fillMode = kCAFillModeForwards;
basicAnimation.removedOnCompletion = NO;
//加载动画 注意这里是layer层的动画
[button.layer addAnimation:basicAnimation forKey:nil];
}
- (void)click:(UIButton *)button {
NSLog(@"click");
}
运行程序点击button,你会发现,只有在初始化的那个位置是能够点击到的,并不能实现点击运动中的button
这里只需要添加一个类CADisplayLink,具体解释看代码实现
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 100, 50, 50);
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 1000;
[self.view addSubview:button];
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
//可以不写fromValue
//起点,fromValue是对象类型,所以CGPoint必须封装成对象
basicAnimation.fromValue = [NSValue valueWithCGPoint:button.center];
//到哪个点
basicAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 550)];
//动画运行总时间
basicAnimation.duration = 100.0;
//重复次数
// basicAnimation.repeatCount = MAXFLOAT;
//是否倒退
// basicAnimation.autoreverses = YES;
//设置为线性移动
basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
//设置视图在动画结束后停留在结束位置,这两个代码同时设置才有效果
basicAnimation.fillMode = kCAFillModeForwards;
basicAnimation.removedOnCompletion = NO;
//加载动画 注意这里是layer层的动画
[button.layer addAnimation:basicAnimation forKey:nil];
//创建CADisplayLink类,iPhone6中等同于屏幕刷新频率为60hz,也就是每秒调用60次displaylinkHandle方法,Pop动画看起来很流畅,就是使用了此机制
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displaylinkHandle)];
//加入到RunLoop主事件中
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)click:(UIButton *)button {
NSLog(@"click");
}
- (void)displaylinkHandle {
//根据tag值获取到前面创建的button
UIButton *getButton = (UIButton *)[self.view viewWithTag:1000];
//获得button的layer层,这里一定是presentationLayer,不然layer不对应
CALayer *layer = (CALayer *)[getButton.layer presentationLayer];
//获取当前layer的中心点
CGPoint point = [[layer valueForKey:@"position"] CGPointValue];
getButton.layer.position = point;
}
现在点击移动中的button,可以看到控制台会不断打印消息,如此便能实现点击效果,这个只是简单的位移动画,要是动画按照贝塞尔曲线运动,view位移动画,或者是仿射变换又该如何操作,贝塞尔曲线运动和位移处理大体相同,就不在赘述了,要是真不会,就给我留言,下面就说说其他两种动画
view位移动画
由于此动画必须是在动画结束时才能进行点击,所以如果要点击移动中的控件,需要将动画暂停,然后触发点击事件,再进行动画,理论上是可行的,一般来说如果需要位移动画完全可以通过layer层动画完成。仿射变换
以中心点为圆心,在圆周上运动
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 100, 30, 30);
button.center = self.view.center;
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 1000;
//设置锚点
button.layer.anchorPoint = CGPointMake(-2, -2);
[self.view addSubview:button];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkHandle)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)click:(UIButton *)button {
NSLog(@"click");
}
- (void)displayLinkHandle {
UIButton *getButton = (UIButton *)[self.view viewWithTag:1000];
getButton.layer.transform = CATransform3DRotate(getButton.layer.transform, M_PI * 2 * (1.0 / 360.0), 0, 0, 1);
}
总结:在遇到问题过程中,需要学会总结,并举一反三才能扩展更多的知识,在使用CADisplayLink类时,需要记的它的方法是每秒调用60次,使用对象方法[displayLink invalidate];可以停止调用