iOS的圓角是一個永恆且艱鉅的問題,蘋果也在iOS 9中優化了cornerRadius屬性,將幀率提高了不少。但是,圓角在iOS程式中使用頻率之高,要求我們必須找到更好的方式去解決這個問題。我看了許多高效新增圓角的部落格,總結了處理圓角的方法。
如何設定圓角
iOS中圓角的新增莫非以下三種模式:
- 設定檢視的layer.cornerRadius屬性
imageView.layer.cornerRadius = imageView.frame.size.width / 2;
imageView.layer.masksToBounds = YES;
複製程式碼
- ✘✘✘ 使用CAShapeLayer和UIBezierPath設定圓角
UIBezierPath *maskBezierPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];
CAShapeLayer *maskShapeLayer = [[CAShapeLayer alloc]init];
maskShapeLayer.frame = imageView.bounds;
maskShapeLayer.path = maskBezierPath.CGPath;
imageView.layer.mask = maskShapeLayer;
複製程式碼
- 使用UIBezierPath和CoreGraphics框架畫出一個圓角
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, [UIScreen mainScreen].scale);
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
複製程式碼
效能的影響
-
設定檢視的layer.cornerRadius屬性。 第一種方式適用於頁面中圓角內容較少的情況,例如個人中心頁面,只有頭像用到了圓角,那麼大費周折的去裁剪、繪製一個圓角遠不如兩個程式碼設定一下cornerRedius屬性來的快,並且對效能的損耗幾乎可以忽略。
-
✘✘✘ 使用CAShapeLayer和UIBezierPath設定圓角。 這種方式同樣是修改了檢視的layer層,在檢視上方新增一層mask遮罩,使檢視看上去為圓角,但是經過各個iOS開發者的實踐測試,用這種方式對效能的損耗甚至超過了第一種方式,這種吃力不好討好的事情,我們拒絕使用它!
-
使用UIBezierPath和CoreGraphics框架畫出一個圓角。 如果你使用了tableView、collectionView,想給它們的cell裡新增圓角,或大量給控制元件們新增了圓角,那再去使用第1種方式何止cornerRadius屬性就不太合適了,過量消耗的記憶體會讓你機器的幀數從50、60降低到10、20,這是一件非常影響使用者體驗的事情,這時這種方法就非常靠譜了。 使用UIBezierPath和CoreGraphics的方式既不會操作layer層,也能夠高效的新增圓角。接下來就為UIImageView寫一個分類,方便在專案裡使用就好。
使用第三種方法使用分類新增圓角的程式碼
寫一個UIImageView的分類,使用下面程式碼新增,確保新增圓角時,imageView.image不為nil即可(因為方法的本質是裁剪UIImage)。
[imageView quickSetCornerRadius:50];
複製程式碼
UIImageView+cornerRadius.h
#import <UIKit/UIKit.h>
@interface UIImageView (cornerRadius)
- (void)quickSetCornerRadius:(CGFloat)cornerRadius;
@end
@interface UIImage (cornerRadius)
- (UIImage *)imageAddCornerWithRadius:(CGFloat)radius andSize:(CGSize)size;
@end
複製程式碼
UIImageView+cornerRadius.m
#import "UIImageView+cornerRadius.h"
@implementation UIImageView (cornerRadius)
- (void)quickSetCornerRadius:(CGFloat)cornerRadius
{
self.image = [self.image imageAddCornerWithRadius:cornerRadius andSize:self.bounds.size];
}
@end
@implementation UIImage (cornerRadius)
- (UIImage *)imageAddCornerWithRadius:(CGFloat)radius andSize:(CGSize)size
{
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CGContextAddPath(contextRef,path.CGPath);
CGContextClip(contextRef);
[self drawInRect:rect];
CGContextDrawPath(contextRef, kCGPathFillStroke);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
複製程式碼