Core Animation核心动画的使用示例

Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。

Core Animation可以用在Mac OS X和iOS平台。

Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

一、CALayer与UIView的关系

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。

其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层:

在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层。

@property(nonatomic,readonly,retain) CALayer *layer;

在ViewController中可以直接使用self.view.layer

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。

二、UIView动画简介

UIView动画可以设置的动画属性有:

  • 大小变化(frame)
  • 拉伸变化(bounds)
  • 中心位置(center)
  • 旋转(transform)
  • 透明度(alpha)
  • 背景颜色(backgroundColor)
  • 拉伸内容(contentStretch)

三、Core Animation结构

626233-43bafe84d8aee5bf.png

其中灰色虚线表示继承关系,红色表示遵守协议。

核心动画中所有类都遵守CAMediaTiming协议。

CAAnaimation是个抽象类,不具备动画效果,必须用它的子类才有动画效果。

CAAnimationGroup和CATransition才有动画效果,

CAAnimationGroup是个动画组,可以同时进行缩放,旋转(同时进行多个动画)。

CATransition是转场动画,界面之间跳转(切换)都可以用转场动画。

CAPropertyAnimation也是个抽象类,本身不具备动画效果,只有子类才有。

CABasicAnimation和CAKeyframeAnimation:

CABasicAnimation基本动画,做一些简单效果。

CAKeyframeAnimation帧动画,做一些连续的流畅的动画。

四、Core Animation的使用

更多基础的详细的介绍可以参考文章最后的文章,后面的这几个文章都写的很不错,就不重复造轮子了,这里主要说下怎么使用。

4.1、最原始的使用

//原始变色
[UIView beginAnimations:@"test" context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
self.view.backgroundColor = [UIColor redColor];
[UIView commitAnimations];

使用beginAnimations标记动画开始,里面可以设置各种参数,比如setAnimationDuration动画时长等

4.2、也可以使用block块

//使用block块变色
    [UIView animateWithDuration:2.0f animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
        self.view.backgroundColor = [UIColor redColor];
    }];

4.3、使用CABasicAnimation来变色

CABasicAnimation是基本动画,通过fromvalue和tovalue来实现开始和结束的动画值

属性说明
fromValuekeyPath相应属性的初始值
toValuekeyPath相应属性的结束值

动画过程说明:

随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。

keyPath内容是CALayer的可动画Animatable属性,比如位置position、背景颜色backgroundColor

同时setRemovedOnCompletion和setFillMode同时设置,来实现结束状态是什么样子

//结束后保持状态
[baseAnimation setRemovedOnCompletion:NO];
[baseAnimation setFillMode:kCAFillModeForwards];

那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变

//使用CABasicAnimation变色
CABasicAnimation *baseAnimation = [CABasicAnimation animation];
[baseAnimation setKeyPath:@"backgroundColor"];
    
//结束后保持状态
[baseAnimation setRemovedOnCompletion:NO];
[baseAnimation setFillMode:kCAFillModeForwards];
//更改位置可以这样设置
//    [baseAnimation setKeyPath:@"position"];
//    [baseAnimation setFromValue:[NSValue valueWithCGRect:CGRectMake(0, 200, 100, 100)]];
//    [baseAnimation setToValue:[NSValue valueWithCGRect:CGRectMake(0, 400, 100, 100)]];

    
[baseAnimation setToValue:(id)[UIColor redColor].CGColor];
[self.view.layer addAnimation:baseAnimation forKey:@"ss"];

这样,就达到了同样的效果。

4.4、groupAnimation动画组的使用

groupAnimation动画组可以使这几个动画同时运行显示,默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间。

比如这里把背景颜色、位置、旋转度同时设置,可以这么用

//使用动画组groupAnimation,组合动画同时运行
CABasicAnimation *baseAnimation = [CABasicAnimation animation];
[baseAnimation setKeyPath:@"backgroundColor"];
[baseAnimation setToValue:(id)[UIColor redColor].CGColor];
    
CABasicAnimation *baseAnimation2 = [CABasicAnimation animation];
[baseAnimation2 setKeyPath:@"position"];
[baseAnimation2 setToValue:[NSValue valueWithCGRect:CGRectMake(0, 200, 100, 100)]];
    
CABasicAnimation *baseAnimation3 = [CABasicAnimation animation];
[baseAnimation3 setKeyPath:@"transform.rotation.y"];
[baseAnimation3 setToValue:[NSNumber numberWithDouble:M_PI*200]];
    
CAAnimationGroup *groupAniation = [[CAAnimationGroup alloc] init];
[groupAniation setAnimations:[NSArray arrayWithObjects:baseAnimation,baseAnimation2,baseAnimation3, nil]];
[groupAniation setDuration:2.0f];
[groupAniation setRepeatCount:1];
[groupAniation setRemovedOnCompletion:NO];
[groupAniation setFillMode:kCAFillModeForwards];
[self.view.layer addAnimation:groupAniation forKey:@"ss"];

4.5、CATransition转场动画的使用

CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点。

UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果。

比如这里使用转场动画来操纵一个UIView,这里的self.m_addView加的有一个图片和一个按钮

self.m_addView = [[UIView alloc] initWithFrame:CGRectMake(10, 400, 300, 300)];
[self.m_addView setHidden:true];
[self.view addSubview:self.m_addView];
    
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
imgView.image = [UIImage imageNamed:@"1.png"];
[self.m_addView addSubview:imgView];
  
UIButton *doneBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 100, 40)];
[doneBtn setTitle:@"D O N E" forState:UIControlStateNormal];
[doneBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[doneBtn addTarget:self action:@selector(endTransformAction) forControlEvents:UIControlEventTouchUpInside];
[self.m_addView addSubview:doneBtn];

点击按钮时,开始做一个翻页的动画

[self.m_addView setHidden:false];
[UIView beginAnimations:@"FlipAni" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
//可以设置开始的回调函数
//    [UIView setAnimationWillStartSelector:@selector(startAni:)];
//可以设置结束完成的回调函数
//    [UIView setAnimationDidStopSelector:@selector(stopAni:)];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.m_addView cache:NO];
   
[UIView commitAnimations];

这样就可以了,当然也可以使用block块来实现同样的目的

//block块转场动画
[self.m_addView setHidden:false];
[UIView transitionWithView:self.m_addView duration:1.0 options:UIViewAnimationOptionTransitionCurlUp animations:^{
      [UIView setAnimationRepeatCount:1];
   } completion:^(BOOL finished) {
      if (finished) {
           NSLog(@"compltion");
        }
 }];

这几个就是最基础的使用,当然core Animation是很强大的,操作layer层。如果需要深入了解原理,可以看后面的参考文章。

五、demo下载

Github下载:https://github.com/DamonHu/LayerTransformDemo

Gitosc下载:http://git.oschina.net/DamonHoo/LayerTransformDemo

六、参考文章

Last modification:February 15th, 2017 at 11:42 pm
如果看了这个文章可以让你少加会班,可以请我喝杯可乐
已打赏名单
微信公众号

2 comments

  1. 东东

  2. 东东

    回复测试代码

    printf("hello word");

Leave a Comment