简单自定义View
1.新建一个继承于UIView的类
2.重载drawRect方法,在方法中进行绘图
带进度的自定义View
1.新建一个继承于UIView的类
2.添加属性,例如进度
2.重载drawRect方法,在方法中根据属性进行绘图
自定义带动态属性(动画)的View
1.新建一个继承于UIView的类
2.添加属性,例如进度
3.新建一个继承于CALayer的类
4.给Layer类添加对应的动态属性,动态属性用NSManaged修饰,在初始化方法总将不再对此属性初始化
5.在View中重载open class var layerClass: Swift.AnyClass { get }属性,返回自定义的Layer类型
6.在Layer中重载init方法来提供给View自动生成layer属性实例
7.在Layer中重载override init(layer: Any)方法来根据当前Layer生成关键帧插值图层
8.在Layer中重载class func needsDisplay(forKey key: String) -> Bool方法,来判断当前属性改变是否需要重新绘制。如果想实现自定义动画就需要重载这个方法,当key等于扩展属性时return yes即可,其余的调用父类的needsDisplay方法。如果当前属性需要重绘便会自动调用 setNeedsDisplay,这样就会触发重绘
9.在Layer中重载func action(forKey event: String) -> CAAction?方法,为动态属性返回CAAction(CAAnimation),其余的调用父类方法。
10.在Layer中重载func display()方法,在方法中创建绘制上下文,进行绘制。在这里创建的上下文就是func draw(in ctx: CGContext)中的上下文。
11.所以也可以在Layer中重载func draw(in ctx: CGContext),来进行绘制
11.如果设置了Layer的Delegate,所以也可以通过实现代理方法func draw(_ layer: CALayer, in ctx: CGContext)方法进行绘制。
注意:drawRect方法不能手动调用,必须通过调用setNeedsDisplay让系统自动调用
来看下 setNeedsDisplay之后layer及其delegate的相关方法调用。
layer方法响应链有两种:
① [layer setNeedDisplay] -> [layer displayIfNeed] -> [layer display] -> [layerDelegate displayLayer:]
② [layer setNeedDisplay] -> [layer displayIfNeed] -> [layer display] -> [layer drawInContext:] -> [layerDelegate drawLayer: inContext:]
参考链接:
钟表实例
进度条实例
NSManaged的说明
OC中@dynamic的作用
路径的绘制
swift路径的绘制