原理(CATransaction)
CATransaction
CATransaction
,又称事务,这东西主要作用是:只要在该”区间”内的layer的可用来做动画的属性改变了,就会以一种过渡的形式来展现。
使用方式如下:
CATransaction.begin() // 开始
CATransaction.setAnimationDuration(4) // 设置时间
self.sublayer.backgroundColor = UIColor.blue.cgColor // do something
CATransaction.commit() // 结束
以上就能开启一个动画了。
为什么有隐式动画
其实系统有个runloop,每一次循环会在起始位置begin
,结束位置commit
,所以内部所有的可用来做动画的属性变化了就都会有动画。 但是一定要保证begin和commit对应,也就是基于栈的操作来对应。
UIView.Animation
那么UIView提供了一套动画的简单写法,但这些操作也只是为了便于使用,而且不至于让使用者造成进栈与出栈不对应的情况发生。
/// 动画开始,对应begin
open class func beginAnimations(_ animationID: String?, context: UnsafeMutableRawPointer?)
/// 动画提交,对应commit
open class func commitAnimations()
/// 又或者下面的动画
UIView.animate(withDuration: 5) {
/// do something
}
可以转换成
CATransaction.begin() // 开始
CATransaction.setAnimationDuration(5) // 设置时间
block() // do something
CATransaction.commit() // 结束
presentation & model
当一个layer的可表现动画的属性发生变化时,会立刻将layer的属性制成变化后的值,但是中间有个动画还要表现,这个会有一个呈现图层来表现。
/// layer的这个属性平时都是nil的,那么当在动画途中时,这个会存在,且是layer的一个完全copy,不过正在动画的值在不断变化,也就是这个是对应呈现图层的layer
open func presentation() -> Self?
/// 这个属性的值是动画后的,不管你现在是不是在动画过程中
open func model() -> Self
那么,有时候需要点击正在位移途中的layer,比如这个layer从位置1移到了位置2,那么这个时候想要在位移过程中,能够处理点击事件,那么就需要根据presentation()
的位置来判断
animation 过程
当layer的属性发生变化时,系统会查找一个可执行的动画。是通过这个func来查找的
class CALayer {
/* Returns the action object associated with the event named by the
* string 'event'. The default implementation searches for an action
* object in the following places:
*
* 1. if defined, call the delegate method -actionForLayer:forKey:
* 2. look in the layer's `actions' dictionary
* 3. look in any `actions' dictionaries in the `style' hierarchy
* 4. call +defaultActionForKey: on the layer's class
*
* If any of these steps results in a non-nil action object, the
* following steps are ignored. If the final result is an instance of
* NSNull, it is converted to `nil'. */
open func action(forKey event: String) -> CAAction?
}
查找第一步
看这个layer的delegate有没有实现,如果有会看看actionForLayer:forKey:
有没有实现。如果没有会转入第二步。
actionForLayer:forKey:
介绍:
返回nil,转第二步;返回NSNull(),关闭动画;返回CAAction,会执行返回的具体动画
查找第二步
open var actions: [String : CAAction]?
这个字典定义了对一个属性关键字的动画,会在这里变查找。
我们也可以在创建layer后直接设置好这个字典
如果没查找到转入第三步
查找第三步
open var style: [AnyHashable : Any]?
同第二步,没有转四
查找第四步
/** Action methods. **/
open class func defaultAction(forKey event: String) -> CAAction?
如果都找不到就转这个了,系统提供了针对一些可动画的属性的默认动画。会直接提供的。
question
-
怎么关闭隐式动画?
更改属性时,使用
CATransaction.setDisableActions(true)
即可也可以在
actionForLayer:forKey:
返回NSNull()
-
为什么view没有隐式动画?
actionForLayer:forKey:
提供了一个more 的实现,应该是返回NSNull()
了