測試環境算法
Xcode 11.5app
iPhone 11 Pro Simulator測試
iOS 13.5flex
咱們常常看到,圓角會觸發離屏渲染。但其實這個說法是不許確的,由於圓角觸發離屏渲染也是有條件的!優化
咱們先來看看蘋果官方文檔對於cornerRadius
的描述:ui
Setting the radius to a value greater than
0.0
causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’scontents
property; it applies only to the background color and border of the layer. However, setting themasksToBounds
property totrue
causes the content to be clipped to the rounded corners.spa
咱們發現設置cornerRadius
大於0時,只爲layer的backgroundColor
和border
設置圓角;而不會對layer的contents
設置圓角,除非同時設置了layer.masksToBounds
爲true
(對應UIView的clipsToBounds
屬性)。3d
若是這時,你認爲layer.masksToBounds
或者clipsToBounds
設置爲true
就會觸發離屏渲染,這是不徹底正確的。code
咱們先打開模擬器的離屏渲染顏色標記:orm
layer.masksToBounds
或者clipsToBounds
,其默認值爲NO
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
// 設置背景色
view1.backgroundColor = UIColor.redColor;
// 設置邊框寬度和顏色
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
// 設置圓角
view1.layer.cornerRadius = 100.0;
view1.center = self.view.center;
[self.view addSubview:view1];
}
複製代碼
咱們看到只有背景色、邊框以及圓角的時候,確實不會觸發離屏渲染。
layer.masksToBounds
或者clipsToBounds
爲YES
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
// 設置背景色
view1.backgroundColor = UIColor.redColor;
// 設置邊框寬度和顏色
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
// 設置圓角
view1.layer.cornerRadius = 100.0;
// 設置裁剪
view1.clipsToBounds = YES;
view1.center = self.view.center;
[self.view addSubview:view1];
}
複製代碼
當咱們開啓layer.masksToBounds
或者clipsToBounds
時,一樣的沒有觸發離屏渲染。這是由於咱們尚未設置圖片。
layer.masksToBounds
或者clipsToBounds
爲YES
,同時設置圖片- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
// 設置背景色
view1.backgroundColor = UIColor.redColor;
// 設置邊框寬度和顏色
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
//設置圖片
view1.layer.contents = (__bridge id)[UIImage imageNamed:@"pkq"].CGImage;
// 設置圓角
view1.layer.cornerRadius = 100.0;
// 設置裁剪
view1.clipsToBounds = YES;
view1.center = self.view.center;
[self.view addSubview:view1];
}
複製代碼
當咱們開啓layer.masksToBounds
或者clipsToBounds
時,同時設置圖片時,就會觸發離屏渲染。
其實不光是圖片,咱們爲視圖添加一個有顏色、內容或邊框等有圖像信息的子視圖也會觸發離屏渲染。
有圖像信息還包括在視圖或者layer的draw方法中進行繪製等。
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
// 設置背景色
view1.backgroundColor = UIColor.redColor;
// 設置邊框寬度和顏色
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
// 設置圓角
view1.layer.cornerRadius = 100.0;
// 設置裁剪
view1.clipsToBounds = YES;
// 子視圖
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100.0, 100.0)];
// 下面3個任何一個屬性
// 設置背景色
view2.backgroundColor = UIColor.blueColor;
// 設置內容
view2.layer.contents = (__bridge id)([UIImage imageNamed:@"pkq"].CGImage);
// 設置邊框
view2.layer.borderWidth = 2.0;
view2.layer.borderColor = UIColor.blackColor.CGColor;
[view1 addSubview:view2];
view1.center = self.view.center;
[self.view addSubview:view1];
}
複製代碼
圖層的疊加繪製大概遵循「畫家算法」。
油畫算法:先繪製場景中的離觀察者較遠的物體,再繪製較近的物體。
先繪製紅色部分,再繪製⻩色部分,最後再繪製灰⾊部分,便可解決隱藏面消除的問題。即將場景按照物理距離和觀察者的距離遠近排序,由遠及近的繪製便可。
當咱們設置了cornerRadius
以及masksToBounds
進行圓角+裁剪時,masksToBounds
裁剪屬性會應用到全部的圖層上。
原本咱們從後往前繪製,繪製完一個圖層就能夠丟棄了。但如今須要依次在 Offscreen Buffer中保存,等待圓角+裁剪處理,即引起了 離屏渲染 。
背景色、邊框、背景色+邊框,再加上圓角+裁剪,根據文檔說明,由於 contents = nil 沒有須要裁剪處理的內容,因此masksToBounds
設置爲YES
或者NO
都沒有影響。
一旦咱們 爲contents設置了內容 ,不管是圖片、繪製內容、有圖像信息的子視圖等,再加上圓角+裁剪,就會觸發離屏渲染。
不必定是直接爲contents賦值!
關於圓角,iOS 9及以後的系統版本,蘋果進行了一些優化。
layer.contents
/imageView.image
咱們只設置contents
或者UIImageView
的image
,並加上圓角+裁剪,是不會產生離屏渲染的。但若是加上了背景色、邊框或其餘有圖像內容的圖層,仍是會產生離屏渲染。
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//設置圖片
view1.layer.contents = (__bridge id)[UIImage imageNamed:@"qiyu"].CGImage;
// 設置圓角
view1.layer.cornerRadius = 100.0;
// 設置裁剪
view1.clipsToBounds = YES;
view1.center = self.view.center;
[self.view addSubview:view1];
}
複製代碼
其實這也是能夠理解的,由於只有 單層 內容須要添加圓角和裁切,因此能夠不須要用到離屏渲染技術。但若是加上了背景色、邊框或其餘有圖像內容的圖層,就會產生爲 多層 添加圓角和裁切,因此仍是會觸發離屏渲染(如1中的第3個例子)。
因此,咱們在使用相似於UIButton
的視圖的時候須要注意:
UIButton
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 建立一個button視圖
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//設置圖片
[button setImage:[UIImage imageNamed:@"pkq"] forState:UIControlStateNormal];
button.center = self.view.center;
[self.view addSubview:button];
}
複製代碼
咱們爲UIButton
設置一個圖片,其實會添加一個UIImageView
。
爲UIButton
添加圓角和裁剪,則會觸發離屏渲染。
// 設置圓角
button.layer.cornerRadius = 100.0;
// 設置裁剪
button.clipsToBounds = YES;
複製代碼
若是改成UIButton
中的UIImageView
添加圓角和裁剪,則 不會觸發離屏渲染。
// 設置圓角
button.imageView.layer.cornerRadius = 100.0;
// 設置裁剪
button.imageView.clipsToBounds = YES;
複製代碼
更多渲染問題能夠看下面這篇文章。
若是以爲本文對你有所幫助,給我點個贊吧~