iOS ,记录一下自己对于圆角优化性能的理解

11 篇文章 0 订阅

公司开发多个项目中,视图的圆角是不可避免的,也是增加美观度的一种方式,下面谈一下“老生常谈”的圆角问题,以下是个人理解。

圆角的常用设法,cornerRadius设置圆角 , masksToBounds把整个图层蒙上圆角 。

_whiteView.layer.cornerRadius = 5;
_whiteView.layer.masksToBounds = YES;

但是maskToBounds就是会导致离屏渲染。下面说离屏渲染的事。如果设置圆角量少,用这种方式是没有问题的,而且在iOS9之后苹果优化了它导致的离屏渲染。但是量大的时候就会降低我们的fps,造成卡顿。

 

关于离屏渲染,个人理解

关于屏幕渲染,1.屏幕渲染:是在当前屏幕的缓存区进行 。2 .离屏渲染:是新开辟一个离屏缓存区,在这个缓存区进行图形渲染。

    当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染被唤起。

离屏渲染详细内容就是在图形渲染到屏幕上的时候,开辟出一个离屏缓存区(1),在离屏渲染的时候是先在当屏缓存区(2)切换到离屏缓存区,在离屏缓存区进行操作,并在屏幕缓存区之间不断地进行上下文切换,等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上有需要将上下文环境从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。导致性能问题的罪魁祸首就是上下文不断的进行切换,造成fps降低,卡顿。

那么一般解决的方式众多,下面系统的说一下自己认为可行的:

1. UI给一张带圆形的遮挡图,就是中间是需要的圆角图形,透明的,圆角外是自己所需要设置的底色

2.光栅化:view..layer.shouldRasterize = YES ; 

当shouldRasterize设成true时,layer被渲染成一个bitmap,并缓存起来,等下次使用时不会再重新去渲染了。

对于layer的shouldRasterize属性默认为NO,将此属性设置为YES时,会在对应的本地坐标空间创建一张bitmap图片,用来缓存图片,当在layer上添加filters或者shadow effects等特效时,将自动开启光栅化的功能,光栅化的开启与否不会影响最总的render output 既最终的渲染输出,但是有一点要注意,开启光栅化虽然不会影响最终的输出结果,但是却可能严重影响性能。

3.使用贝塞尔画出视图圆角。

-(void)setCornerRadiusWithRectCorner:(UIRectCorner)rectCorner radius:(CGFloat)radius {
    CAShapeLayer *maskLayer = nil;
    if (!self.layer.mask) {
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(radius, radius)];
        maskLayer = [CAShapeLayer layer];
        maskLayer.frame = self.bounds;
        maskLayer.path = maskPath.CGPath;
        self.layer.mask = maskLayer;
    }
}

CAShapeLayer属于QuartzCore框架,继承自CALayer。CAShapeLayer是在坐标系内绘制贝塞尔曲线的,通过绘制贝塞尔曲线,设置shape(形状)的path(路径),从而绘制各种各样的图形以及不规则图形。因此,使用CAShapeLayer需要与UIBezierPath一起使用。
UIBezierPath类允许你在自定义的 View 中绘制和渲染由直线和曲线组成的路径.。你可以在初始化的时候直接为你的UIBezierPath指定一个几何图形。
通俗点就是UIBezierPath用来指定绘制图形路径,而CAShapeLayer就是根据路径来绘图的。

4. 图形上下文对image进行处理圆角

- (instancetype)circleImage
{
// 开启图形上下文 (这个就用到前面的UIView的分类可以直接点出来)
UIGraphicsBeginImageContext(self.size);

// 获得上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// 矩形框
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

// 添加一个圆
CGContextAddEllipseInRect(ctx, rect);

// 裁剪(裁剪成刚才添加的图形形状)
CGContextClip(ctx);

// 往圆上面画一张图片
[self drawInRect:rect];

// 获得上下文中的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

// 关闭图形上下文
UIGraphicsEndImageContext();

return image;
}
- (UIImage*)imageAddCornerWithRadius:(CGFloat)radius andSize:(CGSize)size andImage:(UIImage *)image{
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CGContextAddPath(ctx,path.CGPath);
CGContextClip(ctx);
[image drawInRect:rect];
CGContextDrawPath(ctx, kCGPathFillStroke);
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
} 

当然除了以上两种,还有其他对图片进行处理的,有的开发是直接提供的圆角的头像之类的,这样就太省事省力了。

5.就是使用第三方库,下载下来的图片进行圆角处理,再进行缓存(YYWebImage是带圆角处理的)。类似第四种

总结:一般情况是不需要对圆角这么优化的,系统的设置方式就能搞定

     圆角视图量多的话我们也可以择优。一般让UI给覆盖图,这种局限性大,如果是项目工程内是做大量的一种圆角视图,当然这种是可以的。就怕好多处量大而且不是很统一的,我一般用的就是处理图片,也就是第4种 。以上是不同项目中都用到的一些方式。

自己突然想随便写写,并不涉及技术高低之说,还有其他优化的方式我接触不多,如果浏览者有疑问或者建议意见的话,可以留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值