日常我们使用layer的两个属性,简单的两行代码就能实现圆角的呈现
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = 10.f;
由于设置masksToBounds 会导致离屏渲染(离屏渲染:GPU在当前屏幕缓冲区外新开辟一个渲染缓冲区进行工作),这会给我们带来额外的性能损耗,如果这样的圆角操作达到一定数量,会触发缓冲区的频繁合并和上下文的的频繁切换,性能的代价会宏观地表现在用户体验上----掉帧。
当然这些效果不会直接显示在屏幕上,可以使用Instruments的CoreAnimation检测,当然你也可以自己写一个检测帧频的方法。
那如何高效的为UIImageView创建圆角?
修改image为圆角图片
图片进行了切角处理后,将得到的含圆角UIImage通过setImage传给了UIImageView。操作没有触发GPU离屏渲染,过程在CPU内完成。
/** * @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered */
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
if (nil == UIGraphicsGetCurrentContext()) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
[cornerPath addClip];
[image drawInRect:self.bounds];
id processedImageRef = (__bridge id _Nullable)(UIGraphicsGetImageFromCurrentImageContext().CGImage);
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
self.layer.contents = processedImageRef;
});
});
}
圆角路径直接用贝塞尔曲线绘制,并且还有个意想不到的效果是可以选择哪几个角有圆角效果。
延伸:如何高效的为UIView创建圆角?
做法的原理是手动画出圆角的image,在UIView上增加一层UIImageView,将image赋值给UIImageView。
当然,简单的做法是设计的美工自己做一张带有圆角效果的图片,根据大小拉伸。这样的一个好处是以防美工随意更改圆角的角度😄
网友评论