2022-06-09老生常談的圓角和陰影問題

最近開始重構(gòu)我們小說的項(xiàng)目,有機(jī)會(huì)很詳細(xì)的去思考一些細(xì)節(jié)問題。在造輪子的時(shí)候弄到添加圓角和陰影的工具,就又回顧一下這個(gè)部分的知識(shí),并且實(shí)踐了一下,什么情況才會(huì)產(chǎn)生離屏渲染。

以下使用iOS15.4模擬器進(jìn)行測試。控件選用的button,因?yàn)楸旧矶鄨D層,設(shè)置了背景顏色和image

情況一 使用系統(tǒng)方法進(jìn)行操作
//button測
    UIButton * testView = [[UIButton alloc]init];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.width.height.mas_equalTo(100);
    }];

    [testView setImage:[UIImage imageNamed:@"search_icon"] forState:(UIControlStateNormal)];
    
    //系統(tǒng)方法切圓角 加邊框 加陰影
    testView.layer.cornerRadius = 40.0;

直接設(shè)置圓角沒產(chǎn)生離屏渲染!


image.png
  • 開啟clipsToBounds
testView.clipsToBounds = YES;

產(chǎn)生離屏渲染

  • 開啟masksToBounds
testView.layer.masksToBounds = YES;

產(chǎn)生離屏渲染!


image.png

但是!
1、如果我這個(gè)button不設(shè)置image,然后開啟testView.layer.masksToBounds = YES或者testView.clipsToBounds = YES;是不產(chǎn)生離屏渲染的。

2、或者Button設(shè)置了圖片,但是不設(shè)置背景色,然后設(shè)置testView.layer.masksToBounds = YES或者testView.clipsToBounds = YES;也不會(huì)產(chǎn)生離屏渲染!

//button測
    UIButton * testView = [[UIButton alloc]init];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.width.height.mas_equalTo(100);
    }];
testView.layer.cornerRadius = 40.0;
    testView.layer.masksToBounds = YES;
//    testView.clipsToBounds = YES;
1、2分別設(shè)置一種的情況,不產(chǎn)生離屏渲染

也就是Button會(huì)產(chǎn)生離屏渲染的情況是:
設(shè)置了背景+設(shè)置了Image,并且開啟了testView.layer.masksToBounds = YES或者testView.clipsToBounds = YES;都會(huì)造成離屏渲染。

  • 加邊框+加圓角+開啟畫布烘托
   testView.layer.cornerRadius = 40.0;
    testView.layer.borderWidth = 3;
    testView.layer.borderColor = [UIColor redColor].CGColor;
   testView.layer.masksToBounds = YES;

產(chǎn)生離屏渲染。


image.png
  • 加邊框+開啟畫布烘托,不加圓角
    不會(huì)產(chǎn)生離屏渲染!
    testView.layer.borderWidth = 3;
    testView.layer.borderColor = [UIColor redColor].CGColor;
   testView.layer.masksToBounds = YES;
image.png
  • 加陰影
testView.layer.shadowColor = [UIColor blackColor].CGColor;
testView.layer.shadowOffset = CGSizeMake(0,10);
testView.layer.shadowOpacity = 1;

產(chǎn)生離屏渲染!只要用系統(tǒng)的方法加了陰影,就會(huì)產(chǎn)生離屏渲染!

image.png

因?yàn)橹貥?gòu)項(xiàng)目么,所以想找到比較好的方案,盡量不產(chǎn)生離屏渲染,試了下網(wǎng)絡(luò)呼聲最高的貝塞爾曲線去實(shí)現(xiàn)。

情況二 使用貝塞爾曲線實(shí)現(xiàn)
  • 貝塞爾畫Button圓角
   //貝塞爾切圓角
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(40, 40)];
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame = CGRectMake(0, 0, 100, 100);
    layer.path = bezierPath.CGPath;
    testView.layer.mask = layer;

產(chǎn)生離屏渲染!

  • 貝塞爾繪制View圓角
    也會(huì)產(chǎn)生離屏渲染。繪制UIImageView也會(huì)產(chǎn)生離屏渲染。
image.png
  • 貝塞爾繪制陰影
 UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
    testView.layer.masksToBounds = NO;
    testView.layer.shadowColor = UIColor.blackColor.CGColor;
    testView.layer.shadowOffset = CGSizeMake(0, 5);
    testView.layer.shadowOpacity = 0.5f;
    testView.layer.shadowPath = shadowPath.CGPath;

不會(huì)產(chǎn)生離屏渲染!


image.png
產(chǎn)生離屏渲染的原因

之前做過一次Tabel的優(yōu)化有提過關(guān)于離屏渲染相關(guān)的。核心是因?yàn)?code>畫家算法。
簡單來說,如果圖層可以一次性繪制完畢,那么就不需要保存在離屏緩沖區(qū),不需要進(jìn)行二次繪制,就不會(huì)造成離屏渲染。

如果圖層較多,并且開啟了畫布烘托,那么系統(tǒng)會(huì)讓所有的圖層都遵守這個(gè)烘托規(guī)則,當(dāng)實(shí)施畫家算法的時(shí)候,較遠(yuǎn)的圖層繪制完畢不會(huì)立刻被丟棄,就會(huì)存在離屏緩沖區(qū),等待二次繪制,完成程序指令期待的繪制結(jié)果。詳細(xì)過程可以了解下畫家算法(搜索引擎搜一下??)。

總結(jié)

經(jīng)過以上的實(shí)踐,我們來總結(jié)一下會(huì)產(chǎn)生離屏渲染的情況。

  • UIButton這種多圖層的UI,設(shè)置了背景色+Image+開啟了畫布烘托,會(huì)造成離屏渲染。
  • 系統(tǒng)方法繪制陰影,會(huì)發(fā)生離屏渲染。
  • 使用貝塞爾曲線繪制圓角,會(huì)產(chǎn)生離屏渲染。
  • UIImageView設(shè)置了圖片,設(shè)置了背景色,開啟畫布烘托,并且進(jìn)行系統(tǒng)切圓角,產(chǎn)生離屏。

不會(huì)產(chǎn)生的情況:

  • 多圖層的控件只設(shè)置了圖片或者只設(shè)置背景,進(jìn)行切圓角,設(shè)置邊框,開啟畫布烘托不會(huì)產(chǎn)生離屏;
  • 普通View設(shè)置個(gè)圓角一般沒啥事兒。這個(gè)貌似是在iOS9之后優(yōu)化的,不會(huì)產(chǎn)生離屏了。

不知道有沒有搞錯(cuò)的情況,有問題留言哦~

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

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

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