CALayer-拾遺

CALayer是什么?

在iOS中,UIView是我們構(gòu)建UI的基礎(chǔ)單元,而UIView之所以可以顯示各種元素靠的就是CALayer。
當(dāng)創(chuàng)建UIView對(duì)象時(shí),UIView內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)層,通過UIView的layer可以獲取這個(gè)主layer,當(dāng)UIView需要顯示內(nèi)容到屏幕上時(shí),會(huì)執(zhí)行一系列繪制方法將所有內(nèi)容繪制在自己的層上,繪制完畢后,系統(tǒng)會(huì)將層拷貝到屏幕上,這樣就完成了UIView的顯示。

CALayer和UIView如何選擇?

CALayer和UIView都可以顯示內(nèi)容,那他們有什么區(qū)別?
通過類的定義可以知道CALayer是繼承自CALayer的,而UIView是繼承自UIResponder,從這我們就了解了CALayer不能響應(yīng)事件,而需要響應(yīng)事件的時(shí)候,我們就需要使用UIView,如果不需要響應(yīng)事件時(shí),兩者都可以,但是CALayer的性能會(huì)比UIView好很多。

CALayer的常見屬性

  • bounds - 設(shè)置CALayer的寬度和高度
  • backgroundColor - 設(shè)置CALayer的背景色
  • position - 設(shè)置CALayer的中心點(diǎn)
  • anchorPoint - 設(shè)置錨點(diǎn),初始值為(0.5, 0.5),它是表示位于寬高的比例,初始位置與position重合
    前面幾個(gè)屬性很好理解,下面詳細(xì)記錄下anchorPoint

anchorPoint

重新設(shè)置anchorPoint,相當(dāng)于anchorPoint的坐標(biāo)不動(dòng),然后移動(dòng)frame
如果設(shè)置0,0,則需要往右下角的點(diǎn)移動(dòng)view,直到比例滿足0,0的位置
如果設(shè)置0,1,則需要往右上角移動(dòng)view,直到比例滿足0,1的位置
如果設(shè)置為1,0,則需要向左下角移動(dòng)view,直到比例滿足1,0的位置
如果設(shè)置為1,1,則需要向左上角移動(dòng)view,,直到比例滿足1,1的位置

layer如何為圖片設(shè)置圓角與陰影

我們知道,在UIImageView顯示圖片的時(shí)候,只是設(shè)置cornerRadius,是無法實(shí)現(xiàn)的,必須要加上maskToBounds=YES,這是為什么?
當(dāng)繪制一張圖片到圖層上的時(shí)候會(huì)重新創(chuàng)建一個(gè)圖層添加到當(dāng)前圖層,這樣設(shè)置圓角后,只是底圖層有圓角效果,而子圖層并沒有圓角效果,所以圓角效果是顯示不出來的,這時(shí)只有設(shè)置masksToBounds為YES時(shí),才能讓子圖層按底圖層裁剪子圖層!

那我設(shè)置了圓角效果后,再加上陰影效果,這種情況會(huì)怎么樣呢?
不難想,陰影效果肯定會(huì)失效,masksToBounds會(huì)將子視圖裁剪掉,而陰影效果恰巧是作為外邊框繪制的,這樣就會(huì)被裁剪掉
如果我們希望圖層展示圖片既有圓角又有陰影,要怎么解決呢
可以通過曲線救國,借助兩個(gè)圖層來做,容器圖層添加陰影效果
圖片圖層做圖片裁剪

下面再看下在layer層同時(shí)設(shè)置圖片與陰影的方法

在看這個(gè)問題前,我們先來看下layer如何設(shè)置圖片,以及出現(xiàn)圖片倒立的問題如何解決
  1. 通過contents賦值設(shè)置圖片
- (void)drawCornerAndShadow {   
    CALayer *photoLayer = [CALayer new];
    photoLayer.bounds = bounds;
    photoLayer.position = position;
    photoLayer.backgroundColor = [UIColor redColor].CGColor;
    photoLayer.cornerRadius = cornerRadius;
    photoLayer.masksToBounds = YES;
    photoLayer.borderColor = [UIColor whiteColor].CGColor;
    photoLayer.borderWidth = borderW;
    UIImage *image=[UIImage imageNamed:@"photo.png"];
    [photoLayer setContents:(id)image.CGImage];
    [self.view.layer addSublayer:photoLayer];
}

通過這種設(shè)置不會(huì)產(chǎn)生倒立的問題

  1. 通過layer的delegate進(jìn)行繪制
- (void)drawCornerAndShadow {
    CALayer *photoLayer = [CALayer new];
    photoLayer.bounds = bounds;
    photoLayer.position = position;
    photoLayer.backgroundColor = [UIColor redColor].CGColor;
    photoLayer.cornerRadius = cornerRadius;
    photoLayer.masksToBounds = YES;
    photoLayer.borderColor = [UIColor whiteColor].CGColor;
    photoLayer.borderWidth = borderW;
   
    //設(shè)置CALayerDelegate
    photoLayer.delegate = self;
    [self.view.layer addSublayer:photoLayer];
    //調(diào)用圖層setNeedDisplay,否則代理不會(huì)執(zhí)行
    [photoLayer setNeedsDisplay];
}

-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{          
    CGContextSaveGState(ctx);
    UIImage *image=[UIImage imageNamed:@"photo.png"];
    //注意這個(gè)位置是相對(duì)于圖層而言的不是屏幕
    CGContextDrawImage(ctx, CGRectMake(0, 0, Photo_W, Photo_W), image.CGImage);
}

這種顯示圖片的方法,有幾個(gè)關(guān)鍵步驟需要做:

  • 設(shè)置CALayerDelegate代理為當(dāng)前VC
  • 實(shí)現(xiàn)代理并在代理中設(shè)置圖片
  • 執(zhí)行l(wèi)ayer的setNeedsDisplay,否則代理不會(huì)執(zhí)行

這種情況雖然圖片顯示出來了,但是圖片確是倒立的
如何解決倒立的問題呢

首先,我們要了解為什么圖片會(huì)倒立?
因?yàn)閁IKit的坐標(biāo)系,與CoreGraphics中坐標(biāo)系不同,UIKit是x軸向右為正向,y軸向下為正向;而CoreGraphics是x軸向右為正向,y軸向上為正向。
所以解決這個(gè)問題,只需要讓圖片以x軸旋轉(zhuǎn)180度即可

  • 方案一 drawLayer新增選擇方法
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{    CGContextSaveGState(ctx);
    //解決圖片倒立的問題-方法1
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -Photo_W);
    
    UIImage *image=[UIImage imageNamed:@"photo.png"];
    //注意這個(gè)位置是相對(duì)于圖層而言的不是屏幕
    CGContextDrawImage(ctx, CGRectMake(0, 0, Photo_W, Photo_W), image.CGImage);
}
  • 方案二 設(shè)置transform
photoLayer.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
  • 方案三 通過keyPath設(shè)置tansform
[photoLayer setValue:@M_PI forKeyPath:@"transform.rotation.x"];

接下來我們來看下如果通過兩個(gè)layer完成圓角與陰影的設(shè)置

- (void)drawCornerAndShadow {
    CGPoint position = CGPointMake(160, 200);
    CGRect bounds = CGRectMake(0, 0, Photo_W, Photo_W);
    CGFloat cornerRadius = Photo_W/2;
    CGFloat borderW = 2;
    CALayer *layerShadow = [CALayer new];
    layerShadow.bounds = bounds;
    layerShadow.position = position;
    layerShadow.cornerRadius = cornerRadius;
    layerShadow.shadowColor = [UIColor orangeColor].CGColor;
    layerShadow.shadowOffset = CGSizeMake(2, 1);
    layerShadow.shadowOpacity = 1;
    layerShadow.borderColor = [UIColor yellowColor].CGColor;
    layerShadow.borderWidth = borderW;
    [self.view.layer addSublayer:layerShadow];
    
    CALayer *photoLayer = [CALayer new];
    photoLayer.bounds = bounds;
    photoLayer.position = position;
    photoLayer.backgroundColor = [UIColor redColor].CGColor;
    photoLayer.cornerRadius = cornerRadius;
    photoLayer.masksToBounds = YES;
    photoLayer.borderColor = [UIColor whiteColor].CGColor;
    photoLayer.borderWidth = borderW;
    UIImage *image=[UIImage imageNamed:@"photo.png"];
    [photoLayer setContents:(id)image.CGImage];
    [self.view.layer addSublayer:photoLayer];
}

簡(jiǎn)簡(jiǎn)單單,完成設(shè)置

生活如此美好,今天就點(diǎn)到為止。。。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容