UIView和CALayer

1 两者关系

UIView来自UIKit框架,继承自UIResponder,CALayer来自QuartzCore框架,继承自NSObject。
两者互相依赖,UIView负责管理CALayer,在add或remove时,将其layer进行对应的处理,是对CALayer的封装,可以响应和处理事件。而CALayer则绘制和展示内容。
分离开来是为了单一职责,方便维护和拓展,在Mac OS 平台上,将UIView对应的是NSView,实现了复用。

UIView的很多属性是依赖CALayer实现的,比如frame\bounds\center\alpha\clipsToBounds,最终调用了CALayer的frame\bounds\position\opacity\masksToBounds。而Layer的frame则依赖自身的anchorPotin、position、bounds和transform。

比如UIView的alpha、hidden的获取和设置,就是调用了CALayer的opacty和hidden。

内容的绘制

UIView是CALayer的delgate,可以实现代理来参与内容等绘制,CALayerDelegate有以下可选方法:

@protocol CALayerDelegate <NSObject>
@optional
- (void)displayLayer:(CALayer *)layer;
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
- (void)layerWillDraw:(CALayer *)layer
- (void)layoutSublayersOfLayer:(CALayer *)layer;
- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event;

通过实现这些方法,UIView也可以来绘制内容。
-[UIView setNeedsDisplay]方法会标记内容需要更新,在下一个绘制周期到来时,内容会进行更新。
-[CALayer display],会调用delegate(即UIView)的-[UIView displayLayer:]方法。如果未实现,则调用-[CALayer drawInContext: ]。
-[CALayer drawInContext: ]会调用delegate的-[UIView drawLayer:inContext:]方法。
而默认的-[UIView drawLayer:inContext:]方法会尝试调用-[UIView drawRect:]方法。
调用顺序如下,自上而下,如果上面的实现了,则后面的不会被调用。

-[UIView displayLayer:]
-[UIView drawLayer:inContext:]
-[UIView drawRect:]

如果UIView通过重写上面其中一个方法即可参与内容的绘制。
UIView有个contentMode的属性,当设置为UIViewContentModeRedraw时,如果更新bound,也会导致内容更新。

对于自定义的View,通常会重写layoutSubviews方法,在里面更新subview的位置,但这个方法不应该直接调用,而是调用-[UIView setNeedsLayout]或-[UIView layoutIfNeeded],等待系统来更新layout。
前者设置一个标记,等待runloop的下一个周期,进行更新。
后者看是否有更新标记,有则立刻更新,否则直接返回。
所有需要立即更新就这样调用:

-[UIView setNeedsLayout];
-[UIView layoutIfNeeded];
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值