1. UIView相应事件,layer直接继承自NSObject不响应事件。
2. Frame映射
layer的frame由anchorPoint,position,bounds,和 transform 共同决定的,而一个 View 的 frame 只是简单的返回 Layer的 frame,同样 View 的 center和 bounds 也是返回 Layer 的一些属性。
anchorPoint:作用比较像图钉,这一点是固定的,围绕该点可以做旋转变化。坐标系采用的是本身坐标系。
position:是anchorPoint相对于superLayer的位置,坐标系采用的是父级layer的坐标系。
上述两个点是同一个点对应的不同的参考坐标系。
设置view的frame、bounds、center是调用layer的frame、bounds、position的设置方法。
3. UIView侧重内容的管理,CALyer侧重内容的绘制
4. 修改UIView的属性(位置、背景色等)不会产生动画效果,当对单个非rootLayer(每个view都有一个layer,称作rootLayer)的属性进行修改时会产生隐形动画。
任何可动画的layer属性发生改变时,会查找action来执行之一layer的属性改变。
view作为layer的delegate,layer属性发生改变时,向delegate发送消息询问改变属性的action。
delegate有三种相应方式:
- 返回动作对象,layer直接执行这个动作。
- 返回nil,layer到其他地方寻求相应动作。
- 返回NSNull,到此停止,不执行动作。
一般情况下,layer属性改变,其delegate view返回的是NSNull,也就是说不会产生动画效果;只有当layer的属性改变发生在block中时[UIView annimateWithDuration:anmations:]
,view返回的是实际动作,因此执行了动画效果。
layerClass方法可以为view创建layer指定使用的类,因此可以用来重写 layer 子类中的 addAnimation:forKey: 并输出一些东西来验证它是否确实被调用。
MyLayer:
class MyLayer: CALayer {
override func add(_ anim: CAAnimation, forKey key: String?) {
print("adding animation:" + anim.debugDescription)
super.add(anim, forKey: key)
}
}
MyView
class MyView: UIView {
//view创建layer时,为其指定使用哪一个类来创建layer,如下例子使用MyLayer创建layer
override class var layerClass: AnyClass{
return MyLayer.self
}
}
动画block
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let view = MyView()
self.view.addSubview(view)
UIView.animate(withDuration: 3) {
view.alpha = 0.5
}
}
结果:
View-Layer协作