小小圆角问题,正常情况下,我们不需要过多关心,但当屏幕内比较多的时候,还是有必要了解下性能问题的

一、设置CALayer的cornerRadius

这是最常用的,也是最简单的。

cornerRadius属性影响layer显示的background颜色和前景框border,但对layer的contents不起作用。

所以一个imgView(类型为UIImageView)的image不为空,设置imgView.layer的cornerRadius,是看不出显示圆角效果的,因为image是imgView.layer的contents部分;只有将layer的masksToBounds属性也设置为YES,才能绘制出圆角效果。

但是cornerRadius>0,masksToBounds=YES,会触发GPU的离屏渲染,当一个屏幕上有多处触发离屏渲染,会影响一定性能。

(如果查看性能概况,可参考查看这篇:通过勾选Instruments->Core Animation->Color Offscreen-Rendered Yellow,可以看到屏幕上触发离屏渲染的会被渲染成黄色。)

离屏渲染会降低fps,苹果也意识到会产生性能问题,所以iOS9以后的系统里能不产生离屏渲染的地方也就不用离屏渲染了。

比如对UIImageView里png图片设置圆角不会触发离屏渲染。

1、对contents为空的视图设置圆角imageView.layer.backgroundColor = [[UIColor redColor] CGColor];imageView.layer.cornerRadius = 25;
2、对contents不为空的视图设置圆角imageView.image = [UIImage imageNamed:@"img"];imageView.layer.cornerRadius = 5;imageView.layer.masksToBounds = YES;//必须加

这里延伸一下,如果对一个label或button设置圆角,也可以使用layer.backgroundColor和layer.cornerRadius设置,而不需要layer.maskstoBounds。

这样不会触发离屏渲染,所以ios9之后,可以直接这样做。

二、设置CALayer的mask

通过设置view.layer的mask属性,可以将另一个layer盖在view上,也可以设置圆角,但是mask同样会触发离屏渲染。

有两种方式来生成遮罩:

一是通过图片生成,图片的透明度影响着view绘制的透明度,图片遮罩透明度为1的部分view被绘制成的透明度为0,相反图片遮罩透明度为0的部分view被绘制成的透明度为1。

二是通过贝塞尔曲线生成,view中曲线描述的形状部分会被绘制出来。

// 通过图片生成遮罩,
UIImage *maskImage = [UIImage imageNamed:@"someimg"];
CALayer *mask = [CALayer new];
mask.frame = CGRectMake(0, 0, maskImage.size.width, maskImage.size.height);
mask.contents = (__bridge id _Nullable)(maskImage.CGImage);
view.layer.mask = mask;//通过贝塞尔曲线生成
CAShapeLayer *mask = [CAShapeLayer new];
mask.path = [UIBezierPath bezierPathWithOvalInRect:view.bounds].CGPath;
view.layer.mask = mask;

第一种找遮罩图麻烦点,第二种足以。

三、通过Core Graphics重新绘制带圆角的视图

通过CPU重新绘制一份带圆角的视图来实现圆角效果,会大大增加CPU的负担,而且相当于多了一份视图拷贝会增加内存开销。但是就显示性能而言,由于没有触发离屏渲染,所以能保持较高帧率。下例是绘制一个圆形图片,绘制其它UIView并无本质区别。重新绘制的过程可以交由后台线程来处理。

@implementation UIImage (CircleImage)- (UIImage *)drawCircleImage {CGFloat side = MIN(self.size.width, self.size.height);UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, [UIScreen mainScreen].scale);CGContextAddPath(UIGraphicsGetCurrentContext(),[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, side, side)].CGPath);CGContextClip(UIGraphicsGetCurrentContext());CGFloat marginX = -(self.size.width - side) / 2.f;CGFloat marginY = -(self.size.height - side) / 2.f;[self drawInRect:CGRectMake(marginX, marginY, self.size.width, self.size.height)];CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);UIImage *output = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return output;
}
@end//在需要圆角时调用如下
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{UIImage *img = [[UIImage imageNamed:@"image.png"] drawCircleImage];dispatch_async(dispatch_get_main_queue(), ^{view.image = img;});
});

其实感觉这种方式有我不是很推荐,我测试过几次,cpu会大大增加,内存也会有一点增加,而且当屏幕内大概有200个圆角时,偶发一次会崩溃。

四、通过混合图层

此方法就是在要添加圆角的视图上再叠加一个部分透明的视图,只对圆角部分进行遮挡。其实就是中间圆形部分透明,不遮挡底部的控件,不过同时也需要遮挡颜色和view背景色一致才行。

此方法虽然是最优解,没有离屏渲染,没有额外的CPU计算,但是应用范围有限。

总结

  1. 在可以使用混合图层遮挡的场景下,优先使用第四种方法。
  2. 即使是非iOS9以上系统,几种办法介于伯仲之间,甚至第一种方法使用更简单,不过在iOS9以上由于没有了离屏渲染更是首选。
  3. 方法二和方法三由于使用了贝塞尔曲线,都可以应对复杂的圆角。只不过前者牺牲帧率,后者需要大量计算和增加部分内存,需要实际情况各自取舍。

如果需要测试代码,在我的测试demo里

点击这里获取

enjoy~

转载于:https://www.cnblogs.com/yajunLi/p/6509158.html

iOS设置圆角的四种方法相关推荐

  1. iOS设置圆角的4种方法

    1 直接layer层的设置(不推荐) 其中的masksToBounds会实现离屏渲染 GPU会在当前屏幕缓冲区开辟一个新的缓冲区进行工作 也就是离屏渲染 这会给我们带来额外的性能损耗 如果这样的圆角操 ...

  2. iOS-UITextField中给placeholder动态设置颜色的四种方法

    思路分析: 0.自定义UITextField 1.设置占位文字的颜色找-->placeholderColor,结果发现UITextField没有提供这个属性 2.在storyboard/xib中 ...

  3. iOS设置圆角的三种方式

    第一种方法:通过设置layer的属性 最简单的一种,但是很影响性能,一般在正常的开发中使用很少. UIImageView *imageView = [[UIImageView alloc]initWi ...

  4. IOS启程06—iOS设置圆角图片

    iOS设置圆角的三种方式 1 方法一 通过设置layer的属性 UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMak ...

  5. java indexof 子字符串_Java中字符串中子串的查找共有四种方法(indexof())

    Java中字符串中子串的查找共有四种方法(indexof()) Java中字符串中子串的查找共有四种方法,如下: 1.int indexOf(String str) :返回第一次出现的指定子字符串在此 ...

  6. IOS中Json解析的四种方法

    2019独角兽企业重金招聘Python工程师标准>>> 作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此& ...

  7. 【转】IOS中Json解析的四种方法

    原文网址:http://blog.csdn.net/enuola/article/details/7903632 作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有 ...

  8. html获取data-*值,html5 获取和设置data-*属性值的四种方法讲解

    1.获取id的对象 2.需要获取的就是data-id 和 dtat-vice-id的值 一:getAttribute()方法 const getId = document.getElementById ...

  9. ios打包ipa的四种实用方法(.app转.ipa)

    [原]ios打包ipa的四种实用方法(.app转.ipa) 总结一下,目前.app包转为.ipa包的方法有以下几种: 1.Apple推荐的方式,即实用xcode的archive功能 Xcode菜单栏- ...

  10. 【原】ios打包ipa的四种实用方法(.app转.ipa)

    原文地址为: [原]ios打包ipa的四种实用方法(.app转.ipa) 总结一下,目前.app包转为.ipa包的方法有以下几种: 1.Apple推荐的方式,即实用xcode的archive功能 Xc ...

最新文章

  1. OpenCV Python教程(1、图像的载入、显示和保存)
  2. 独家 | 高季尧:定制化优化算法的应用与威力(附PPT)
  3. 科研|Science回应中国燃料电池研究“造假”:发函重点关注,之前撤稿率100%
  4. 阿里青橙奖名单公布,23位院士、2位图灵奖得主推荐
  5. Linux之ping命令使用详解—网络故障定位(六)
  6. python myqr 二维码生成
  7. 基于前后端分离实现阿里云对象存储小案例
  8. boost::hana::on用法的测试程序
  9. 7月9日王者荣耀服务器维护,王者荣耀 7月9日体验服停机更新公告
  10. Android实现飘动的旗帜效果实例
  11. 红旗7.0 rc1 版编辑开始菜单
  12. 【直播预告】“CCF-NLP走进高校”系列之“走进郑州大学”
  13. HDU Fibonacci
  14. 聊聊 Material Design 里,阴影的那些事儿!
  15. 列出访问ftp 文件传输服务器过程,FTP文件传输协议简介及命令描述
  16. Python 接口并发测试详解
  17. socket 服务器端和客户端通信,面向TCP的
  18. 台式计算机拆装过程和注意事项,怎么组装台式电脑 台式电脑组装注意事项
  19. 行业承压虎牙营收持续稳健,电竞浪潮中把握长期价值
  20. sudo rosdep init 失败的解决方法(适用于非自身设备网络、证书等故障的情况)

热门文章

  1. zepto.js学习笔记01
  2. sqlalchemy按月水平分表、python元类、动态映射表名automap_base\ 模型类
  3. docker安装mysql并配置文件_Docker安装mysql,并自定义my.cnf
  4. astype和squeeze 函数
  5. 【Caffe安装】Ubuntu14.04上Caffe配置安装(Only CPU)
  6. no override found for vtkpolydatamapper解决方法
  7. mysql5.7.11源码安装_centos 7.0安装MySQL Community Server 5.7.11 源码编译安装
  8. php 5.6.27 在某些机器上正常,thinkphp5开发的网站出现”No input file specified”(php版本5.6.27)...
  9. Java 对象数组的定义与用法详解
  10. android.jar 位置,Android 导入jar包 so模块--导入放置的目录