案例解读
在我们日常开发过程中 ,经常使用layer.cornerRadius的方式来设置圆角。那到底会不会带来离屏渲染呢 。今天我们来研究一下。
下面是几个不同形式的layer.cornerRadius圆角案例
//1.按钮存在背景图片
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
btn1.frame = CGRectMake(100, 30, 100, 100);
btn1.layer.cornerRadius = 50;
[self.view addSubview:btn1];
btn1.backgroundColor = [UIColor blueColor];
[btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
btn1.clipsToBounds = YES;
//2.按钮不存在背景图片
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
btn2.frame = CGRectMake(100, 180, 100, 100);
btn2.layer.cornerRadius = 50;
btn2.backgroundColor = [UIColor blueColor];
[self.view addSubview:btn2];
btn2.clipsToBounds = YES;
//3.UIImageView 设置了图片+背景色;
UIImageView *img1 = [[UIImageView alloc]init];
img1.frame = CGRectMake(100, 320, 100, 100);
img1.backgroundColor = [UIColor blueColor];
[self.view addSubview:img1];
img1.layer.cornerRadius = 50;
img1.layer.masksToBounds = YES;
img1.image = [UIImage imageNamed:@"btn.png"];
//4.UIImageView 只设置了图片,
无背景色;
UIImageView *img2 =
[[UIImageView alloc]init];
img2.frame = CGRectMake(100, 480, 100, 100);
[self.view addSubview:img2];
img2.layer.cornerRadius = 50;
img2.layer.masksToBounds = YES;
img2.image = [UIImage imageNamed:@"btn.png"];
运行的效果如图所示
首先开启模拟器的离屏渲染检测
结果显示
layer.cornerRadius就一定会产生离屏渲染。
其产生的原因有如下几个 :
- 当图片大小比UIImageView的大小要大,并且
clipsToBounds设置的属性为true,这时候,会产生 图片的裁剪。就会产生离屏渲染。 - 有背景颜色和背景图片一起渲染。个人理解为,有背景颜色 和和背景图片 都包含 ,会产生不同的层次。因而会产生离屏渲染。
离屏渲染原理
app 为了提高渲染效率 ,开辟了 offscreen Buffer 和FrameBuffer 两个缓冲区,目的是为了以空间换取时间。提前进行渲染(offscreenBuffer)可以提高复用目的
还有在特殊效果时 ,屏幕需要使用额外的offscreen Buffer 来保存中间状态,不得不使用离屏渲染,如圆角、阴影。
,
但是离屏渲染渲染也会带来性能问题--容易掉帧.
离屏渲染产生的原因主要有两方面:
1.在VSync(垂直脉冲)信号作用下,视频控制器每隔16.67ms就会去帧缓冲区(当前屏幕缓冲区)读取渲染后的数据;但是有些效果被认为不能直接呈现于屏幕前,而需要在别的地方做额外的处理,进行预合成。
比如图层属性的混合体再没有预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染。屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示之前必须在一个屏幕外上下文中被渲染(不论CPU还是GPU)。
2.有些视图渲染后的纹理需要被多次复用,但屏幕内的渲染缓冲区是实时更新的,所以需要通过开辟屏幕外的渲染缓冲区,将视图的内容渲染成纹理并缓存,然后再需要的时候在调入屏幕缓冲区,可以避免多次渲染的开销。
典型的例子就是光栅化。光栅化就是通过把视图的内容渲染成纹理并缓存,等到下次调用的时候直接去缓存的取出纹理,但是更新内容时候,会启用离屏渲染,所以更新的代价比较大,只能用于静态内容;而且如果光栅化的元素100ms没有被使用,也将被移除,故而不常用元素的光栅化并不会优化显示。
注意:光栅化的元素,总大小限制为2.5倍的屏幕。