UITableview优化之圆角设置

24 篇文章 1 订阅
18 篇文章 0 订阅

一、最简单的设置圆角

	//头像圆角
	icon.layer.cornerRadius = 20
	icon.layer.masksToBounds = true

这种设置方法会造成离屏渲染

什么是离屏渲染

GPU渲染机制
CPU 计算好显示内容提交到 GPU,GPU 渲染完成后将渲染结果放入帧缓冲区,随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。
GPU屏幕渲染有以下两种方式:

  1. On-Screen Rendering意为当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。
  2. Off-Screen Rendering意为离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。

为什么会使用离屏渲染

当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染被唤起。
屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示之前在一个屏幕外上下文中被渲染(不论CPU还是GPU)。
所以当使用离屏渲染的时候会很容易造成性能消耗,
因为在OPENGL里离屏渲染会单独在内存中创建一个屏幕外缓冲区并进行渲染,而屏幕外缓冲区跟当前屏幕缓冲区上下文切换是很耗性能的。

二、CAShapeLayer和UIBezierPath设置圆角

//MARK:圆角图片给imageView添加一个扩展
extension UIImageView {
    /**
     圆角的大小:corderSize,
     corners:那些需要圆角
     自动布局下切记一定设置imageSize
     */
    func cornerImageView(corderSize: CGFloat, corners: UIRectCorner, imageSize: CGSize) -> Void {
        let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize.init(width: corderSize, height: corderSize))
        bounds = CGRect.init(origin: CGPoint.zero, size: imageSize)
        let maskLayer = CAShapeLayer.init()
        maskLayer.path = maskPath.cgPath;
        maskLayer.frame = bounds
        layer.mask = maskLayer
    }
    /**
     圆角的大小:corderSize,
     自动布局下切记一定设置imageSize
     */
    func cornerImageView(corderSize: CGFloat, imageSize: CGSize) -> Void {
        bounds = CGRect.init(origin: CGPoint.zero, size: imageSize)
//        self.image = UIImage.init(named: imageName)
        let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize.init(width: 20, height: 5))
        let maskLayer = CAShapeLayer.init()
        maskLayer.path = maskPath.cgPath;
        maskLayer.frame = bounds
        layer.mask = maskLayer
    }
}

三、贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角

//MARK:圆角图片给imageView添加一个扩展
func bezierPathCorner(corderSize: CGFloat, imageSize: CGSize) {
       //开始对imageView进行画图
        bounds = CGRect.init(origin: CGPoint.zero, size: imageSize)
        UIGraphicsBeginImageContextWithOptions(imageSize, false, 1.0)
        //使用贝塞尔曲线画出一个圆形图
        UIBezierPath.init(roundedRect: bounds, cornerRadius: corderSize).addClip()
        draw(bounds)
        image = UIGraphicsGetImageFromCurrentImageContext();
        //结束画图
        UIGraphicsEndImageContext()
    }

方法二和方法三对比

  1. CAShapeLayer继承于CALayer,可以使用CALayer的所有属性值;
  2. CAShapeLayer需要贝塞尔曲线配合使用才有意义(也就是说才有效果)
    使用CAShapeLayer(属于CoreAnimation)与贝塞尔曲线可以实现不在view的drawRect(继承于CoreGraphics走的是CPU,消耗的性能较大)方法中画出一些想要的图形
  3. CAShapeLayer动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况。
  4. CAShapeLayer的内存消耗少,渲染速度快,建议使用方法二

提示:官方对离屏渲染产生性能问题也进行了优化

  1. iOS 9.0 之前UIimageView跟UIButton设置圆角都会触发离屏渲染。
  2. iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的。

终极圆角设置:给UIView写一个扩展类

extension UIView {
    /**
     圆角的大小:corderSize,
     自动布局下切记一定设置imageSize
     */
    func cornerSets(corderSize: CGFloat, viewSize: CGSize) {
        bounds = CGRect.init(origin: CGPoint.zero, size: viewSize)
        let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize.init(width: 20, height: 5))
        let maskLayer = CAShapeLayer.init()
        maskLayer.path = maskPath.cgPath;
        maskLayer.frame = bounds
        layer.mask = maskLayer
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值