最近開始重構(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)生離屏渲染!

- 開啟
clipsToBounds
testView.clipsToBounds = YES;
產(chǎn)生離屏渲染
- 開啟
masksToBounds
testView.layer.masksToBounds = YES;
產(chǎn)生離屏渲染!

但是!
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;

也就是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)生離屏渲染。

- 加邊框+開啟畫布烘托,不加圓角
不會(huì)產(chǎn)生離屏渲染!
testView.layer.borderWidth = 3;
testView.layer.borderColor = [UIColor redColor].CGColor;
testView.layer.masksToBounds = YES;

- 加陰影
testView.layer.shadowColor = [UIColor blackColor].CGColor;
testView.layer.shadowOffset = CGSizeMake(0,10);
testView.layer.shadowOpacity = 1;
產(chǎn)生離屏渲染!只要用系統(tǒng)的方法加了陰影,就會(huì)產(chǎn)生離屏渲染!

因?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)生離屏渲染。

- 貝塞爾繪制
陰影
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)生離屏渲染!

產(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ò)的情況,有問題留言哦~