美文网首页iOS相关
iOS图层树理解

iOS图层树理解

作者: 任同学少年 | 来源:发表于2017-05-12 13:36 被阅读316次

    iOS图层树(图层的树状结构)

    CoreAnimation

    屏幕上不同的可视内容(可分解成各个独立的图层)通过CoreAnimation引擎组合显示在屏幕上,存在图层树体系中.而这个树就是UIKit所能看到的一个个控件的基础

    CALayer

    CALayer类和UIView相似,两者都是存储在图层树中的矩形块,都可以包含内容,eg:文本,图片或者背景色,或者管理子视图,也可以通过一些方法和属性来做动画和变换.两者不同之处:UIView处理用户交互,CALayer则不处理交互

    CALayer属性

    contents

    CaLayer这个属性contents,这个属性的类型被定义为id,但是如果这个值被赋值的类型不是CGImage,所得到的图层会是空白的.所以iOS开发中赋值类型经常是CGImage,其他类型没有什么意义.

    contents这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。一些初识Core Animation的iOS开发者可能会对这个感到困惑。

    layer.contents = image.CGImage;
    

    如果你是ARC环境,运行此语句,需要加(__bridge id),如果MRC则不需要.ARC环境下,如下:

    layer.contents = (__bridge id)image.CGImage;
    

    contentGravity

    同UIImageView的ContentMonde属性.
    contentGravity常用的值有:
    • kCAGravityCenter
    • kCAGravityTop
    • kCAGravityBottom
    • kCAGravityLeft
    • kCAGravityRight
    • kCAGravityTopLeft
    • kCAGravityTopRight
    • kCAGravityBottomLeft
    • kCAGravityBottomRight
    • kCAGravityResize
    • kCAGravityResizeAspect
    • kCAGravityResizeAspectFill

    maskToBounds

    同UIView的clipsToBounds属性,以用来决定是否显示超出边界的内容

    contentsRect

    contentsRect在app中最有趣的地方在于一个叫做image sprites(图片拼合)的用法。如果你有游戏编程的经验,那么你一定对图片拼合的概念很熟悉,图片能够在屏幕上独立地变更位置。抛开游戏编程不谈,这个技术常用来指代载入拼合的图片,跟移动图片一点关系也没有。
    典型地,图片拼合后可以打包整合到一张大图上一次性载入。相比多次载入不同的图片,这样做能够带来很多方面的好处:内存使用,载入时间,渲染性能等等
    2D游戏引擎入Cocos2D使用了拼合技术,它使用OpenGL来显示图片。不过我们可以使用拼合在一个普通的UIKit应用中,就是使用contentsRect

    contentsCenter

    看名字你可能会以为它可能跟图片的位置有关,不过这名字着实误导了你。contentsCenter其实是一个CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。 改变contentsCenter的值并不会影响到寄宿图的显示,除非这个图层的大小改变了,你才看得到效果。

    Custome Drawing

    给contents赋CGImage的值不是唯一的设置寄宿图的方法。我们也可以直接用Core Graphics直接绘制寄宿图。能够通过继承UIView并实现-drawRect:方法来自定义绘制。
    -drawRect: 方法没有默认的实现,因为对UIView来说,寄宿图并不是必须的,它不在意那到底是单调的颜色还是有一个图片的实例。如果UIView检测到-drawRect: 方法被调用了,它就会为视图分配一个寄宿图,这个寄宿图的像素尺寸等于视图大小乘以 contentsScale的值。
    如果你不需要寄宿图,那就不要创建这个方法了,这会造成CPU资源和内存的浪费,这也是为什么苹果建议:如果没有自定义绘制的任务就不要在子类中写一个空的-drawRect:方法。
    当视图在屏幕上出现的时候 -drawRect:方法就会被自动调用。-drawRect:方法里面的代码利用Core Graphics去绘制一个寄宿图,然后内容就会被缓存起来直到它需要被更新。虽然-drawRect:方法是一个UIView方法,事实上都是底层的CALayer安排了重绘工作和保存了因此产生的图片。

    CALayerDelegate

    CALayerDelegate是一个非正式协议,其实就是说没有CALayerDelegate @protocol可以让你在类里面引用啦.当需要被重绘时,CALayer会请求它的代理给他一个寄宿图来显示。它通过调用下面这个方法做到的:

    - (void)displayLayer:(CALayerCALayer *)layer;
    

    如果代理不实现-displayLayer:方法,CALayer就会转而尝试调用下面这个方法:

    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
    

    举一个例子:

    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIView *layerView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        CALayer *calayer = [CALayer layer];
        
        calayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
        
        calayer.backgroundColor = [UIColor cyanColor].CGColor;
        
        calayer.delegate = self;
        
        calayer.contentsScale = [UIScreen mainScreen].scale;
        
        [self.layerView.layer addSublayer:calayer];
        
        [calayer display];
    }
    
    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
    {
        CGContextSetLineWidth(ctx, 10.0f);
        CGContextSetStrokeColorWithColor(ctx, [UIColor orangeColor].CGColor);
        CGContextStrokeEllipseInRect(ctx,layer.bounds);
    }
    
    
    

    图层

    布局

    UIView有三个比较重要的布局属性:frame,bounds和center,CALayer对应地叫做frame,bounds和position。为了能清楚区分,图层用了“position”,视图用了“center”,但是他们都代表同样的值。

    Z坐标轴

    CALayer存在于一个三维空间当中。除了我们已经讨论过的position和anchorPoint属性之外,CALayer还有另外两个属性,zPosition和anchorPointZ,二者都是在Z轴上描述图层位置的浮点类型。
    zPosition最实用的功能就是改变图层的显示顺序

    CAlayer响应链相关方法

    CALayer并不关心任何响应链事件,所以不能直接处理触摸事件或者手势。但是它有一系列的方法帮你处理事件:-containsPoint:和-hitTest:。

    拉伸过滤

    minificationFilter和magnificationFilter属性.
    当图片需要显示不同的大小的时候,有一种叫做拉伸过滤的算法就起到作用了。它作用于原图的像素上并根据需要生成新的像素显示在屏幕上。
    CALayer为此提供了三种拉伸过滤方法,他们是:
    • kCAFilterLinear
    • kCAFilterNearest
    • kCAFilterTrilinear
    具体效果可以自己去比较,不一一列出来了

    相关文章

      网友评论

        本文标题: iOS图层树理解

        本文链接:https://www.haomeiwen.com/subject/vsbztxtx.html