iOS性能最佳实践之——圆角和阴影的正确使用姿势

图片使用阴影的正确姿势

错误示范:会导致离屏渲染

imageView.layer.shadowOpacity = 0.5;

正确做法:通过shadowPath,告诉CoreAnimation你要渲染的形状,减少离屏渲染

1
2
imageView.layer.shadowOpacity = 0.5;
imageView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:imageView.bounds] CGPath];

对图片做圆角处理的正确姿势

错误示范:
给imageView加cornerRadius后用masksToBounds切。同时加上cornerRadius和masksToBounds后,会触发离屏幕渲染,如果一个Cell里有多个这样的图片,滑动的时候GPU压力会很大,从而导致严重的掉帧。

1
2
3
4
UIImage *image = [UIImage imageNamed:@"IMG_6083"];
imageView.image = image;
imageView.layer.cornerRadius = CGRectGetWidth(imageView.frame)/ 4.0;
imageView.layer.masksToBounds = YES;

正确做法:
通过Core Graphics创建一块位图画布,将图片切成需要的形状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+ (id)createRoundedRectImage:(UIImage *)image size:(CGSize)size radius:(int)radius {
size = CGSizeMake(size.width * image.scale, size.height * image.scale);
radius = radius * image.scale;
UIImage *img = image;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, CGImageGetBitsPerComponent(image.CGImage), 4 * size.width, CGImageGetColorSpace(image.CGImage), kCGImageAlphaPremultipliedFirst);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
CGContextBeginPath(context);
addRoundedRectToPath(context, rect, radius, radius);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
img = [UIImage imageWithCGImage:imageMasked];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageMasked);
return img;
}

给UILabel设置圆角属性

不需要背景颜色时
不需要设置label的backgroundColor,只设置borderWidth、borderColor的label,直接设置cornerRadius,不需要设置masksToBounds = YES,就可以实现圆角功能。

需要背景色
设置label.layer.backgroundColor

1
2
3
4
view.layer.cornerRadius = 20;
view.layer.backgroundColor = [UIColor purpleColor].CGColor;
view.layer.borderColor = [UIColor blackColor].CGColor;
view.layer.borderWidth = 0.5;

cornerRadius属性:
它是影响layer显示的backgroundColor和border,对layer的contents不起作用。
如果UILabel设置backgroundColor,是为contents设置背景色,二不是设定layer的背景色,此时cornerRadius不能实现圆角效果。解决的方法是直接设置label.layer.backgroundColor。

在Cell里,需要响应cell的高亮效果

给UIButton或UITextView等视图做圆角处理

视图里如果不需要呈现图片,可以直接在后台线程画一个带圆角的背景图片,做为子视图。

1
2
3
UIImage *image = [UIImage rounedCornerImage:20 borderWidth:0.5 backgroundColor:[UIColor purpleColor] borderColor:[UIColor clearColor] size:CGSizeMake(CGRectGetWidth(view.frame), CGRectGetHeight(view.frame))];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[button insertSubview:imageView atIndex:0];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+ (UIImage *)rounedCornerImage:(CGFloat)radius
borderWidth:(CGFloat)borderWidth
backgroundColor:(UIColor *)backgroundColor
borderColor:(UIColor *)borderColor
size:(CGSize)size{
CGSize sizeToFit = CGSizeMake(floor(size.width), floor(size.height));
CGFloat halfBorderWidth = (CGFloat)borderWidth / 2.0;
UIGraphicsBeginImageContextWithOptions(sizeToFit, false, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, borderWidth);
CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGFloat width = sizeToFit.width, height = sizeToFit.height;
CGContextMoveToPoint(context, width - halfBorderWidth, radius + halfBorderWidth); // 开始坐标右边开始
CGContextAddArcToPoint(context, width - halfBorderWidth, height - halfBorderWidth, width - radius - halfBorderWidth, height - halfBorderWidth, radius); // 右下角角度
CGContextAddArcToPoint(context, halfBorderWidth, height - halfBorderWidth, halfBorderWidth, height - radius - halfBorderWidth, radius); // 左下角角度
CGContextAddArcToPoint(context, halfBorderWidth, halfBorderWidth, width - halfBorderWidth, halfBorderWidth, radius); // 左上角
CGContextAddArcToPoint(context, width - halfBorderWidth, halfBorderWidth, width - halfBorderWidth, radius + halfBorderWidth, radius); // 右上角
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
UIImage *output = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return output;
}
Blacktea wechat
ex. subscribe to my blog by scanning my public wechat account
记录生活于感悟,您的支持将鼓励我继续创作!