iOS設置圓角方法以及指定位置設圓角

更正

經過代碼以及instruments工具測試,以下更正

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

iOS 9.0 之前UIimageView跟UIButton設置圓角都會觸發離屏渲染。

iOS 9.0 之后UIButton設置圓角會觸發離屏渲染,而UIImageView里png圖片設置圓角不會觸發離屏渲染了,如果設置其他陰影效果之類的還是會觸發離屏渲染的。

第一種方法:通過設置layer的屬性

代碼:

UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"TestImage"]];
// 只需設置layer層的兩個屬性
// 設置圓角
imageView.layer.cornerRadius = 50;
// 將多余的部分切掉
imageView.layer.masksToBounds = YES;
[self.view addSubview:imageView];

這個方法里maskToBounds會觸發離屏渲染,GPU在當前屏幕緩沖區外新開辟了一個渲染緩沖區進行工作,也就是離屏渲染,這會給我們帶來額外的性能損耗,如果這樣的圓角操作達到一定數量,會觸發緩沖區的頻繁合并和上下文的頻繁切換,性能的代價會宏觀的表現在用戶體驗上<掉幀>。

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

代碼:

 UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
 imageView.image = [UIImage imageNamed:@"TestImage.jpg"];
 // 開始對imageView進行畫圖
 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 0.0);
 // 使用貝塞爾曲線畫出一個圓形圖
 [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];
 [imageView drawRect:imageView.bounds];
 imageView.image = UIGraphicsGetImageFromCurrentImageContext();
 // 結束畫圖
 UIGraphicsEndImageContext();
 [self.view addSubview:imageView];
  • UIGraphicsBeginImageContextWithOption(CGSize size, BOOL opaque, CGFloat scale)各參數的含義:
  • size ---新創建的文圖上下文大小
  • opaque --- 透明開關,如果圖形完全不用透明,設置為YES以優化位圖的存儲。
  • scale --- 縮放因子。雖然這里可以用[UIScreen mainScreen].scale來獲取,但實際上設為0后,系統會自動設置正確的比例

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

代碼:

UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
imageView.image = [UIImage imageNamed:@"TestImage.jpg"];

// 開始對imageView進行畫圖
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 0.0);

// 獲取圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// 設置一個范圍
CGRect rect = CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height);

// 根據一個rect創建一個橢圓
CGContextAddEllipseInRect(ctx, rect);

// 裁剪
CGContextClip(ctx);

// 講原照片畫到圖形上下文
[imageView.image drawInRect:rect];

// 從上下文上獲取裁剪后的照片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

// 關閉上下文
UIGraphicsEndImageContext();
imageView.image = image;
[self.view addSubview:imageView];

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

代碼:

UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
imageView.image = [UIImage imageNamed:@"TestImage.jpg"];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners
cornerRadii:imageView.bounds.size];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
// 設置大小
maskLayer.frame = imageView.bounds;
// 設置圖形樣子
maskLayer.path = maskPath.CGPath;
imageView.layer.mask = maskLayer;
[self.view addSubview:imageView];

指定需要的角成為圓角(第四種方法的延伸)

方法:

+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect
                          byRoundingCorners:(UIRectCorner)corners
                                cornerRadii:(CGSize)cornerRadii;
                                
corners參數指定了要成為圓角的角, 枚舉類型如下:
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft     = 1 <&lt; 0,
    UIRectCornerTopRight    = 1 <&lt; 1,
    UIRectCornerBottomLeft  = 1 <&lt; 2,
    UIRectCornerBottomRight = 1 <&lt; 3,
    UIRectCornerAllCorners  = ~0UL
};

實現代碼:

UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 200, 200)];
imageView.image = [UIImage imageNamed:@"TestImage.jpg"];

// 繪制圓角 需設置的圓角 使用"|"來組合
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerTopLeft |
UIRectCornerBottomRight cornerRadii:CGSizeMake(30, 30)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];

// 設置大小
maskLayer.frame = imageView.bounds;

// 設置圖形樣子
maskLayer.path = maskPath.CGPath;
imageView.layer.mask = maskLayer;
[self.view addSubview:imageView];

效果圖:


image.png

然而第四種方法并不可取,存在離屏渲染。
進過實際測試之后,以及哪種方法最為可取,具體可以參考iOS圓角四種方法的對比以及性能檢測(一定要看哦)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,130評論 1 32
  • 面向對象的三大特性:封裝、繼承、多態 OC內存管理 _strong 引用計數器來控制對象的生命周期。 _weak...
    運氣不夠技術湊閱讀 1,127評論 0 10
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,176評論 4 61
  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,183評論 3 23
  • 死,不僅需要勇氣,也需要智慧。 五十六歲的吳池,就做出了這樣的選擇。兩年前,那個十分不幸的下午三點半,他被確診為韌...
    命自我立閱讀 324評論 2 0