一拧篮、CALayer和UIView
CALayer與UIView類似孕讳,是一些被層級(jí)關(guān)系樹(shù)管理的矩形塊涣易,和UIView的最大不同是不能處理用戶的交互良哲。
每一個(gè)UIView都有一個(gè)CALayer的屬性锹引,它的責(zé)任是創(chuàng)建并且管理這個(gè)圖層矗钟,以確保當(dāng)子視圖層級(jí)關(guān)系變化的時(shí)候,他們的關(guān)聯(lián)圖層也同樣對(duì)應(yīng)在層級(jí)關(guān)系樹(shù)當(dāng)中有相同的操作嫌变。
iOS提供CALayer和UIView兩個(gè)平行的層級(jí)關(guān)系是為了職責(zé)分離吨艇。UIView主要是對(duì)顯示內(nèi)容的管理而 CALayer 主要側(cè)重顯示內(nèi)容的繪制。
CALayer可以做而UIView不可以做得事情:
(1)陰影腾啥,圓角秸应,邊框
(2)3D變換
(3)非矩形范圍
(4)透明遮罩
(5)多級(jí)非線性動(dòng)畫(huà)
CALayer *redLayer = [CALayer layer];
redLayer.backgroundColor = [UIColor redColor].CGColor;
redLayer.frame = CGRectMake(0, 0, 50, 50);
[self.view.layer addSublayer:redLayer];
二、寄宿圖和contents屬性
1.寄宿圖:即為圖層中包含的圖碑宴,CALayer不僅可以創(chuàng)建帶有簡(jiǎn)單顏色的背景圖層软啼,還可以包含一張圖片。
2.contents屬性
CALayer可以通過(guò)一個(gè)contents屬性添加圖片
UIImage *image = [UIImage imageNamed:@"icon_logo"];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 50, 50, 100);
[self.view.layer addSublayer:layer];
layer.contents = (__bridge id)image.CGImage;
需要注意:core foundation 和 cocoa對(duì)象不是類型兼容的延柠,需要通過(guò)bridged 關(guān)鍵字進(jìn)行轉(zhuǎn)換祸挪。在ARC環(huán)境下只需要layer.contents = (id)image.CGImage;
id轉(zhuǎn)換就可以了
3.contentGravity
layer.contentsGravity = kCAGravityResizeAspect;
類似于UIView中的cotentMode
4.contentsScale
contentsScale 屬性定義了寄宿圖的像素尺寸和視圖大小的比例,默認(rèn)為1.0
layer.contentsScale = [UIScreen mainScreen].scale;
5.maskToBounds
maskToBounds對(duì)于超出邊界的內(nèi)存剪裁贞间,和UIView的clipsToBounds一樣
6.contentsRect
contentsRect 是使用了單位坐標(biāo)贿条,單位坐標(biāo)指定在0到1中間,是一個(gè)相對(duì)值增热,默認(rèn)的contentsRect是 {0整以,0,1峻仇,1}公黑,意味著整個(gè)寄宿圖都是可見(jiàn)的,如果我們指定為{0,0凡蚜,0.5人断,0.5}就只能顯示左上角的四分之一的圖片。
這樣我們可以得到一個(gè)實(shí)用的功能朝蜘,圖片拼合的用法——將多張圖片整合到一張大圖上面恶迈,一次性載入,相比多次載入不同的圖片谱醇,好處是:內(nèi)存使用暇仲,載入時(shí)間,渲染性能等等副渴。
//contentsRect 屬性
- (void)createCALayerContentsRect {
CALayer *layer1 = [CALayer layer];
layer1.frame = CGRectMake(200, 100, 50, 50);
[self.view.layer addSublayer:layer1];
CALayer *layer2 = [CALayer layer];
layer2.frame = CGRectMake(300, 100, 50, 50);
[self.view.layer addSublayer:layer2];
[self addSpriteImage:[UIImage imageNamed:@"icon_logo"] withContentRet:CGRectMake(0, 0, 0.5, 0.5) layer:layer1];
[self addSpriteImage:[UIImage imageNamed:@"icon_logo"] withContentRet:CGRectMake(0.5, 0.5, 0.5, 0.5) layer:layer2];
}
- (void)addSpriteImage:(UIImage *)image withContentRet:(CGRect)rect layer:(CALayer *)layer {
layer.contents = (id)image.CGImage;
layer.contentsGravity = kCAGravityResizeAspect;
layer.contentsRect = rect;
}
7.contentsCenter
contentsCenter 與UIImage里的 - resizableImageWithCapInsets:方法類似奈附。
三、圖層幾何學(xué)
1.布局
UIView有三個(gè)布局屬性:frame佳晶,bounds桅狠,center,CALayer對(duì)應(yīng)的叫:frame轿秧,bounds中跌,position
Frame代表圖層的外部坐標(biāo),bounds是內(nèi)部坐標(biāo){0菇篡,0}是圖層的左上角漩符。position相當(dāng)于anchorPoint。
當(dāng)操縱視圖的frame驱还,實(shí)際上改變的是位于視圖下方的CALayer的frame嗜暴,對(duì)于視圖或者是圖層來(lái)說(shuō),frame是根據(jù)bounds议蟆,position闷沥,transform計(jì)算而來(lái)的,當(dāng)對(duì)圖層做變換的時(shí)候咐容,比如旋轉(zhuǎn)或者縮放舆逃,frame實(shí)際上代表了覆蓋在圖層旋轉(zhuǎn)之后的整個(gè)軸對(duì)齊的矩形區(qū)域,frame的寬高和bounds可能不一樣了戳粒。
2.錨點(diǎn)
默認(rèn)來(lái)說(shuō)路狮,anchorpoint位于圖層的中心點(diǎn),但是anchorpoint可以被移動(dòng)蔚约。
self.anchorPoint = CGPointMake(0.5f,0.9f);
3.坐標(biāo)系
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
4.翻轉(zhuǎn)的幾何結(jié)構(gòu)
geometryFlipped 設(shè)置為yes奄妨,則子圖層或者子視圖本來(lái)相對(duì)于左上角放置 改為 相對(duì)于左下角放置;
5.Z坐標(biāo)軸
CALayer存在一個(gè)三維空間當(dāng)中苹祟,除了position和anchorPoint之外砸抛,還有zPosition和anchorPointZ评雌。
可以改變圖層的顯示繪圖順序
6.Hit Testing
CGRectContainsRect(<#CGRect rect1#>, <#CGRect rect2#>)表示rect1和rect2是否相交
CGRectContainsPoint(<#CGRect rect#>, <#CGPoint point#>)表示rect中是否包含point坐標(biāo)
CGRectIntersectsRect(<#CGRect rect1#>, <#CGRect rect2#>)表示rect1中是否包含rect2
-hitTest:方法接受一個(gè)CGPoint類型的參數(shù),返回圖層本身锰悼,用于判斷point點(diǎn)擊了那個(gè)圖層
CGPoint point = [[touches anyObject] locationInView:self.view];
CALayer *layer = [self.view.layer hitTest:point];
NSLog(@"%@",layer);
if (layer == self.redLayer) {
NSLog(@"yes");
}