这篇文章是继笔记-iOS设置圆角方法以及指定位置设圆角文章而写的,因为上篇文章发出来后,没有验证,也有同行的朋友让我给出一些测试数据来证实一下,所以这里就给出一下我个人的一些测试数据,正确是否,还请大家作为参考。--------另外,我写这个仅仅只是自己作为笔记使用,原来都是放在草稿里的,但是手机版的无法查看草稿,所以就发出来,没有想过会有人来看,所以如果有错误的内容误导了大家请原谅,也请发现错误的猿友及时帮忙提出,谢谢大家。
Core Animation工具检测离屏渲染
对离屏渲染的检测,苹果为我们提供了一个测试工具Core Animation。可以在Xcode->Open Develeper Tools->Instruments中找到。
先看看第一种方式:通过设置layer的属性
对UIImageview设置:
结果: 无离屏渲染
滚动的帧率:
结果: 接近60,趋于稳定
对UIButton设置:
结果: 离屏渲染
滚动的帧率:
如果低于40帧每秒,普通用户就会察觉明显的不流畅,现在这样app进入垃圾级别体验了。
对于文本视图实现圆角(UILabel, UIView, UITextField, UITextView
)
均只进行cornerRadius
设置,不进行masksToBounds
的设置
离屏渲染情况:
从上图可以看出,对于UILabel, UIView, UITextField
来说,实现了圆角的设置,并没有产生离屏渲染;而对于UITextView
,产生了离屏渲染。
滚动的帧率:
不存在UITextView
视图的情况下
存在UITextView
视图的情况下
官方对离屏渲染产生性能问题也进行了优化:
iOS9.0之前UIImageView跟UIButton设置圆角都会触发离屏渲染。
iOS9.0之后UIButton设置圆角会触发离屏渲染,而UIImageView设置圆角不会触发离屏渲染了,但是如果设置其他阴影效果之类的还是会触发离屏渲染
第二种方式:使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角
对UIImageview设置:
帧率结果:
对UIButton设置:
帧率结果:
两种设置均是无离屏渲染
第三种方式:使用Core Graphics框架画出一个圆角
对UIImageview设置:
帧率结果:
对UIButton设置:
帧率结果:
两种设置均是无离屏渲染
第四种方式:使用CAShapeLayer和UIBezierPath设置圆角
对UIImageview、UIButton设置:
帧率结果:
两种都是离屏渲染,掉帧更加严重。基本上不能使用。
由上述测试可以知道,我上篇文章里所记笔记是有问题的。这里的测试结果可以看的彻底。
新方法:实际可采取利用
混合图层
在需要裁剪的视图上面添加一层视图,以达到圆角的效果。效果如下:
布局图如下:
对于UIImageView
与UIButton
均可使用,且无离屏渲染
滚动的帧率:
代码如下:
- (void)drawRoundedCornerImage {
UIImageView *iconImgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
iconImgV.image = [UIImage imageNamed:@"icon"];
[self.view addSubview:iconImgV];
[iconImgV mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(iconImgV.size);
make.top.equalTo(self.view.mas_top).offset(500);
make.centerX.equalTo(self.view);
}];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[self.view addSubview:imgView];
[imgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(imgView.size);
make.top.equalTo(iconImgV.mas_top);
make.leading.equalTo(iconImgV.mas_leading);
}];
// 圆形
imgView.image = [self drawCircleRadius:100 outerSize:CGSizeMake(200, 200) fillColor:[UIColor whiteColor]];
}
// 绘制圆形
- (UIImage *)drawCircleRadius:(float)radius outerSize:(CGSize)outerSize fillColor:(UIColor *)fillColor {
UIGraphicsBeginImageContextWithOptions(outerSize, false, [UIScreen mainScreen].scale);
// 1、获取当前上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//2.描述路径
// ArcCenter:中心点 radius:半径 startAngle起始角度 endAngle结束角度 clockwise:是否逆时针
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(outerSize.width * 0.5, outerSize.height * 0.5) radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:NO];
[bezierPath closePath];
// 3.外边
[bezierPath moveToPoint:CGPointMake(0, 0)];
[bezierPath addLineToPoint:CGPointMake(outerSize.width, 0)];
[bezierPath addLineToPoint:CGPointMake(outerSize.width, outerSize.height)];
[bezierPath addLineToPoint:CGPointMake(0, outerSize.height)];
[bezierPath addLineToPoint:CGPointMake(0, 0)];
[bezierPath closePath];
//4.设置颜色
[fillColor setFill];
[bezierPath fill];
CGContextDrawPath(contextRef, kCGPathStroke);
UIImage *antiRoundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return antiRoundedCornerImage;
}
此方法就是在要添加的视图上在叠加一个部分透明的视图,只对圆角部分进行遮挡。图层混合的透明度处理方式与mask正好相反。
此方法没有离屏渲染,也可以自定义设置指定任意角为圆角。
总结
- 在可以使用混合图层遮挡的场景下,优先使用。
- 通过.layer属性设置,综合性能上,还是有很大优势的。