筆記-圓角四種方法的對比以及性能檢測

這篇文章是繼筆記-iOS設置圓角方法以及指定位置設圓角文章而寫的,由於上篇文章發出來後,沒有驗證,也有同行的朋友讓我給出一些測試數據來證明一下,因此這裏就給出一下我我的的一些測試數據,正確是否,還請你們做爲參考。--------另外,我寫這個僅僅只是本身做爲筆記使用,原來都是放在草稿裏的,可是手機版的沒法查看草稿,因此就發出來,沒有想過會有人來看,因此若是有錯誤的內容誤導了你們請原諒,也請發現錯誤的猿友及時幫忙提出,謝謝你們。bash

Core Animation工具檢測離屏渲染

對離屏渲染的檢測,蘋果爲咱們提供了一個測試工具Core Animation。能夠在Xcode->Open Develeper Tools->Instruments中找到。markdown

先看看第一種方式:經過設置layer的屬性

對UIImageview設置:app

結果: 無離屏渲染框架

滾動的幀率:工具

結果: 接近60,趨於穩定

對UIButton設置:佈局

結果: 離屏渲染

滾動的幀率:post

若是低於40幀每秒,普通用戶就會察覺明顯的不流暢,如今這樣app進入垃圾級別體驗了。性能

對於文本視圖實現圓角(UILabel, UIView, UITextField, UITextView測試

均只進行cornerRadius設置,不進行masksToBounds的設置優化

離屏渲染狀況:

從上圖能夠看出,對於UILabel, UIView, UITextField來講,實現了圓角的設置,並無產生離屏渲染;而對於UITextView,產生了離屏渲染。

滾動的幀率:
不存在UITextView視圖的狀況下

存在UITextView視圖的狀況下

官方對離屏渲染產生性能問題也進行了優化:

iOS9.0以前UIImageView跟UIButton設置圓角都會觸發離屏渲染。

iOS9.0以後UIButton設置圓角會觸發離屏渲染,而UIImageView設置圓角不會觸發離屏渲染了,可是若是設置其餘陰影效果之類的仍是會觸發離屏渲染

第二種方式:使用貝塞爾曲線UIBezierPath和Core Graphics框架畫出一個圓角

對UIImageview設置:
幀率結果:

對UIButton設置:
幀率結果:

兩種設置均是無離屏渲染

第三種方式:使用Core Graphics框架畫出一個圓角

對UIImageview設置:
幀率結果:

對UIButton設置:
幀率結果:

兩種設置均是無離屏渲染

第四種方式:使用CAShapeLayer和UIBezierPath設置圓角

對UIImageview、UIButton設置:
幀率結果:

兩種都是離屏渲染,掉幀更加嚴重。基本上不能使用。

由上述測試能夠知道,我上篇文章裏所記筆記是有問題的。這裏的測試結果能夠看的完全。

新方法:實際可採起利用

混合圖層

在須要裁剪的視圖上面添加一層視圖,以達到圓角的效果。效果以下:

佈局圖以下:

對於UIImageViewUIButton都可使用,且無離屏渲染

滾動的幀率:

代碼以下:

- (void)drawRoundedCornerImage {
    UIImageView *iconImgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    iconImgV.image = [UIImage imageNamed:@"icon"];
    [self.view addSubview:iconImgV];
    
    [iconImgV mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(iconImgV.size);
        make.top.equalTo(self.view.mas_top).offset(500);
        make.centerX.equalTo(self.view);
    }];
    
    UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    [self.view addSubview:imgView];
    
    [imgView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(imgView.size);
        make.top.equalTo(iconImgV.mas_top);
        make.leading.equalTo(iconImgV.mas_leading);
    }];
    
    // 圓形
    imgView.image = [self drawCircleRadius:100 outerSize:CGSizeMake(200, 200) fillColor:[UIColor whiteColor]];
}

// 繪製圓形
- (UIImage *)drawCircleRadius:(float)radius outerSize:(CGSize)outerSize fillColor:(UIColor *)fillColor {
    UIGraphicsBeginImageContextWithOptions(outerSize, false, [UIScreen mainScreen].scale);
    
    // 一、獲取當前上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    //2.描述路徑
    // ArcCenter:中心點 radius:半徑 startAngle起始角度 endAngle結束角度 clockwise:是否逆時針
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(outerSize.width * 0.5, outerSize.height * 0.5) radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:NO];
    [bezierPath closePath];
    
    // 3.外邊
    [bezierPath moveToPoint:CGPointMake(0, 0)];
    [bezierPath addLineToPoint:CGPointMake(outerSize.width, 0)];
    [bezierPath addLineToPoint:CGPointMake(outerSize.width, outerSize.height)];
    [bezierPath addLineToPoint:CGPointMake(0, outerSize.height)];
    [bezierPath addLineToPoint:CGPointMake(0, 0)];
    [bezierPath closePath];
    
    //4.設置顏色
    [fillColor setFill];
    [bezierPath fill];
    
    CGContextDrawPath(contextRef, kCGPathStroke);
    UIImage *antiRoundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return antiRoundedCornerImage;
}
複製代碼

此方法就是在要添加的視圖上在疊加一個部分透明的視圖,只對圓角部分進行遮擋。圖層混合的透明度處理方式與mask正好相反。 此方法沒有離屏渲染,也能夠自定義設置指定任意角爲圓角。

總結

  • 在可使用混合圖層遮擋的場景下,優先使用。
  • 經過.layer屬性設置,綜合性能上,仍是有很大優點的。
相關文章
相關標籤/搜索