IOS 底层封装Block动画的原理解析

本文解析了UIView与CALayer的关系及核心动画的工作原理。通过理解UIView内部的CALayer及其图形绘制功能,介绍了如何通过Block实现动画效果。Block动画的实现依赖于UIView属性变化触发的CALayer动画机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解析这个之前我们首先要先了解两个知识点:

1.UIView和CALayer的关系

UIView其实内部并没有我们想象的那么强大,他只是负责展示和响应交互事件的,而真正的图形绘制工作,全部是CALayer来完成的,其实CALayer并不属于UIKit架构,而是属于QuartzCore架构,他是一个专门负责图形绘制的工具类,而且是完全跨IOS和OS X平台的。我们之所以感觉不到CALayer的这个功能,是因为UIView在初始化的时候自己创建了一个内置的CALayer对象,然后UIView就变成了CALayer的全权代理了。

2.CAAnimation,CABaseAnimation的相关知识

 这个其实就是IOS核心动画,但是说白了其实就是属性动画,它包括两个重要的部分一个是负责视图显示的presentLayer,一个是负责属性数据的modleLayer,后者是背后的指挥,前者是表面显示,CABaseAnimation有三个很重要的属性就是:1.keyPath:指定动画类型 其实就是view对应的属性名字  2.fromValue:动画的起始值 3.toValue:动画的结束值。

了解了上面的两个知识点后我们再说是如何封装Block动画的。

其实UIView的每个可动画的属性都对应着CALayer的一个属性,当我们给UIView该表它的属性值的时候,CALayer的一个delegate会判断actionForLayer: forKey:当这个方法返回CAAction对象的时候,因为delegate又持有UIView的一个对象,就会把这个CAAction转成一个CAAnimation对象添加到UIView中执行动画,当这个方法返回NSNull的时候,就表示不进行动画只是改变属性,现在大家很明白了,其实很简单,就是当是Block动画的时候,我们只要在block里面设置UIView的属性,上面的那个方法就返回CAAction对象,然后执行动画,如果在block外面,就返回NULL对象,就不做动画,一旦明白了原理就很简单了,其实Block动画的封装就是这么简单。

封装了常见的动画类,很好用 注释非常详细 如下: + (void)showAnimationType:(NSString *)type withSubType:(NSString *)subType duration:(CFTimeInterval)duration timingFunction:(NSString *)timingFunction view:(UIView *)theView { /** CATransition * * @see http://www.dreamingwish.com/dream-2012/the-concept-of-coreanimation-programming-guide.html * @see http://geeklu.com/2012/09/animation-in-ios/ * * CATransition 常用设置及属性注解如下: */ CATransition *animation = [CATransition animation]; /** delegate * * 动画的代理,如果你想在动画开始和结束的时候做一些事,可以设置此属性,它会自动回调两个代理方法. * * @see CAAnimationDelegate (按下command键点击) */ animation.delegate = self; /** duration * * 动画持续时间 */ animation.duration = duration; /** timingFunction * * 用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是 * 先快后慢,先慢后快还是先慢再快再慢. * * 动画的开始与结束的快慢,有五个预置分别为(下同): * kCAMediaTimingFunctionLinear 线性,即匀速 * kCAMediaTimingFunctionEaseIn 先慢后快 * kCAMediaTimingFunctionEaseOut 先快后慢 * kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢 * kCAMediaTimingFunctionDefault 实际效果是动画中间比较快. */ /** timingFunction * * 当上面的预置不能满足你的需求的时候,你可以使用下面的两个方法来自定义你的timingFunction * 具体参见下面的URL * * @see http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/CAMediaTimingFunction_class/Introduction/Introduction.html * * + (id)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y; * * - (id)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y; */ animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunction]; /** fillMode * * 决定当前对象过了非active时间段的行为,比如动画开始之前,动画结束之后. * 预置为: * kCAFillModeRemoved 默认,当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态 * kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态 * kCAFillModeBackwards 和kCAFillModeForwards相对,具体参考上面的URL * kCAFillModeBoth kCAFillModeForwards和kCAFillModeBackwards在一起的效果 */ animation.fillMode = kCAFillModeForwards; /** removedOnCompletion * * 这个属性默认为YES.一般情况下,不需要设置这个属性. * * 但如果是CAAnimation动画,并且需要设置 fillMode 属性,那么需要将 removedOnCompletion 设置为NO,否则 * fillMode无效 */ // animation.removedOnCompletion = NO; /** type * * 各种动画效果 其中除了'fade', `moveIn', `push' , `reveal' ,其他属于似有的API(我是这么认为的,可以点进去看下注释). * ↑↑↑上面四个可以分别使用'kCATransitionFade', 'kCATransitionMoveIn', 'kCATransitionPush', 'kCATransitionReveal'来调用. * @"cube" 立方体翻滚效果 * @"moveIn" 新视图移到旧视图上面 * @"reveal" 显露效果(将旧视图移开,显示下面的新视图) * @"fade" 交叉淡化过渡(不支持过渡方向) (默认为此效果) * @"pageCurl" 向上翻一页 * @"pageUnCurl" 向下翻一页 * @"suckEffect" 收缩效果,类似系统最小化窗口时的神奇效果(不支持过渡方向) * @"rippleEffect" 滴水效果,(不支持过渡方向) * @"oglFlip" 上下左右翻转效果 * @"rotate" 旋转效果 * @"push" * @"cameraIrisHollowOpen" 相机镜头打开效果(不支持过渡方向) * @"cameraIrisHollowClose" 相机镜头关上效果(不支持过渡方向) */ /** type * * kCATransitionFade 交叉淡化过渡 * kCATransitionMoveIn 新视图移到旧视图上面 * kCATransitionPush 新视图把旧视图推出去 * kCATransitionReveal 将旧视图移开,显示下面的新视图 */ animation.type = type; /** subtype * * 各种动画方向 * * kCATransitionFromRight; 同字面意思(下同) * kCATransitionFromLeft; * kCATransitionFromTop; * kCATransitionFromBottom; */ /** subtype * * 当type为@"rotate"(旋转)的时候,它也有几个对应的subtype,分别为: * 90cw 逆时针旋转90° * 90ccw 顺时针旋转90° * 180cw 逆时针旋转180° * 180ccw 顺时针旋转180° */ /** * type与subtype的对应关系(必看),如果对应错误,动画不会显现. * * @see http://iphonedevwiki.net/index.php/CATransition */ animation.subtype = subType; /** * 所有核心动画和特效都是基于CAAnimation,而CAAnimation是作用于CALayer的.所以把动画添加到layer上. * forKey 可以是任意字符串. */ [theView.layer addAnimation:animation forKey:nil]; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值