iOS 控件设置圆角,避免离屏渲染。
离屏渲染:指GPU(图形处理器)在当前屏幕缓冲区外新开辟一个渲染缓冲区进行工作。这会给我们带来额外的性能损耗,如果这样的操作达到一定数量,会触发缓冲区的频繁合并和上下文的的频繁切换,会出现卡顿、掉帧现象。造成离屏渲染的原因有很多,如:shouldRasterize(光栅化)、mask(遮罩层)、shadows(阴影)、EdgeAnntialiasing(抗锯齿)、cornerRadius(圆角)等等。
下面说一下什么情况下设置圆角会造成离屏渲染:
//设置cornerRadius>0且masksToBounds为YES view.layer.cornerRadius = 10.f; view.layer.masksToBounds = YES; //设置cornerRadius>0且masksToBounds为YES view.layer.cornerRadius = 10.f; view.clipToBounds = YES; //像下面设置view.layer.mask UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:imgView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(10.f, 10.f)]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.frame = view.bounds; maskLayer.path = path.CGPath; view.layer.mask = maskLayer;
上面第一种应该是最常用的,是在设置了圆角及masksToBounds为YES时,才会触发离屏渲染,而masksToBounds默认是NO,也就是说只要不设置这个属性就能避免很多情况了,下面说一下如何切一个不触发离屏渲染的圆角:
UIView、UITextField、UITextView等大部分控件都可以像下面这样设置:
view.layer.cornerRadius = 10.f; view.layer.masksToBounds = NO;
有一些特殊情况,UILabel设置时,不要设置label.backgroundColor,应设置:
label.layer.cornerRadius = 10.f; label.layer.backgroundColor = [UIColor whiteColor].CGColor;
有图片的UIButton、UIIMageView,用drawInRect绘制UIImage圆角:
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; UIGraphicsBeginImageContextWithOptions(rect.size, false, [UIScreen mainScreen].scale); CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath); CGContextClip(UIGraphicsGetCurrentContext()); [self drawInRect:rect]; CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
查看离屏渲染,模拟器可以选中“Debug - Color Off-screen Rendered”开启调试,真机可以用Instruments检测,“Instruments - Core Animation - Debug Options - Color Offscreen-Rendered Yellow”开启调试,开启后,有离屏渲染的图层会变成高亮的黄色。
写了个离屏渲染的样例:
下面贴上代码:
控制器ViewController:
#import "ViewController.h" #import "UIImage+HWCorner.h" #define KMainW [UIScreen mainScreen].bounds.size.width @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; //创建控件 [self creatControl]; } - (void)creatControl { CGFloat margin = 20.f; CGFloat cOntrolW= (KMainW - margin * 3) * 0.5; NSArray *titleArray = @[@"离屏渲染", @"非离屏渲染"]; for (int i = 0; i
UIImage分类,UIImage+HWCorner:
#import@interface UIImage (HWCorner) //绘制图片圆角 - (UIImage *)drawCornerInRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; @end /*** ---------------分割线--------------- ***/ #import "UIImage+HWCorner.h" @implementation UIImage (HWCorner) //绘制图片圆角 - (UIImage *)drawCornerInRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius { UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; UIGraphicsBeginImageContextWithOptions(rect.size, false, [UIScreen mainScreen].scale); CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath); CGContextClip(UIGraphicsGetCurrentContext()); [self drawInRect:rect]; CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } @end
最后说一下,只有在大量的离屏渲染情况时才会出现卡顿、掉帧等现象,没必要过分追求容不下一丝黄色。性能上Instruments工具还可以检测很多。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。