iOS高效簡易新增圓角

JatenLv發表於2017-12-21

  iOS的圓角是一個永恆且艱鉅的問題,蘋果也在iOS 9中優化了cornerRadius屬性,將幀率提高了不少。但是,圓角在iOS程式中使用頻率之高,要求我們必須找到更好的方式去解決這個問題。我看了許多高效新增圓角的部落格,總結了處理圓角的方法。

如何設定圓角

  iOS中圓角的新增莫非以下三種模式:

  1. 設定檢視的layer.cornerRadius屬性
imageView.layer.cornerRadius = imageView.frame.size.width / 2;
imageView.layer.masksToBounds = YES;
複製程式碼
  1. ✘✘✘ 使用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;
複製程式碼
  1. 使用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();
複製程式碼

效能的影響

  1. 設定檢視的layer.cornerRadius屬性。   第一種方式適用於頁面中圓角內容較少的情況,例如個人中心頁面,只有頭像用到了圓角,那麼大費周折的去裁剪、繪製一個圓角遠不如兩個程式碼設定一下cornerRedius屬性來的快,並且對效能的損耗幾乎可以忽略。

  2. ✘✘✘ 使用CAShapeLayer和UIBezierPath設定圓角。   這種方式同樣是修改了檢視的layer層,在檢視上方新增一層mask遮罩,使檢視看上去為圓角,但是經過各個iOS開發者的實踐測試,用這種方式對效能的損耗甚至超過了第一種方式,這種吃力不好討好的事情,我們拒絕使用它!

  3. 使用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
複製程式碼

相關文章