iOS - 圓角的設(shè)計(jì)策略 - 及繪畫出沒有離屏渲染的圓角

  • 設(shè)計(jì)圓角時(shí)候?yàn)槭裁葱枰呗?/li>

在我們做APP開發(fā)的過程中,設(shè)計(jì)圓角應(yīng)該是最為基礎(chǔ)的功能之一汇在。就是因?yàn)闀r(shí)常需要用到,所以就有必要考慮到,圓角的設(shè)計(jì)是否會(huì)對(duì)我們APP的流暢性有影響问慎。我們一般設(shè)計(jì)圓角的通用方法:

someView.layer.corneRadius = 10;
someView.maskToBounds = Yes;

由于maskToBounds會(huì)觸發(fā)離屏渲染,所以就有可能導(dǎo)致APP的fps下降挤茄,從而使APP產(chǎn)生卡頓的現(xiàn)象如叼,所以遵從某些簡(jiǎn)單的策略在我們的開發(fā)過程中會(huì)更加有利于APP的流暢。

具體的策略
  • 當(dāng)界面中只有view(不包括view的子類控件)需要設(shè)計(jì)圓角
UIView *someView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
someView.layer.cornerRadius = 10;

注意到:如果僅僅是view需要設(shè)置圓角穷劈,是不要設(shè)置maskToBounds的笼恰,并且someView.layer.cornerRadius并不會(huì)觸發(fā)離屏渲染(很多的文章提到了會(huì)觸發(fā),其實(shí)這是對(duì)該cornerRadius屬性的錯(cuò)誤認(rèn)識(shí)歇终,可能也誤導(dǎo)了許多新手開發(fā)者)挖腰,所以可以安心的設(shè)置


  • 當(dāng)界面中有其他的包含子控件的view,如label练湿,imageView等,需要設(shè)置圓角审轮,但是數(shù)量并不多肥哎。此時(shí)可以安心的使用如下的方法,這里雖然會(huì)觸發(fā)離屏渲染疾渣,但是由于數(shù)量比較少篡诽,所以對(duì)全局的影響一般不會(huì)很大。
someLabel.layer.cornerRadius = 10;
someLabel.maskToBounds = Yes;

  • 但是當(dāng)界面中有非常多需要設(shè)置圓角榴捡,比如tableView中杈女。當(dāng)界面中的tableView有超過25個(gè)圓角(使用上面的方法),那么那么fps將會(huì)下降很多,特別是對(duì)某些控件還設(shè)置了陰影的效果达椰,更加會(huì)加劇界面卡頓的現(xiàn)象翰蠢。此時(shí)對(duì)于不同的控件將采用不同的方法進(jìn)行處理,如下

    1. 對(duì)于label類啰劲,可以通過CoreGraphics來畫出一個(gè)圓角的label
    2. 對(duì)于imageView類梁沧,通過CoreGraphics對(duì)繪畫出來的image進(jìn)行裁邊處理,從而形成一個(gè)圓角的imageView

對(duì)如label類蝇裤,可以用如下方法進(jìn)行繪制廷支,僅給出核心的OC代碼,項(xiàng)目示例代碼可以在github中找到CornerRadius

給UILabel繪畫圓角

- (UIImage *)dr_drawRectWithRoundedCornerRadius:(CGFloat)radius
                                borderWidth:(CGFloat)borderWidth
                            backgroundColor:(UIColor *)backgroundColor
                               borderCorlor:(UIColor *)borderColor {
    CGSize sizeToFit = CGSizeMake([DrCorner pixel:self.bounds.size.width], self.bounds.size.height);
    CGFloat halfBorderWidth = borderWidth / 2.0;

    UIGraphicsBeginImageContextWithOptions(sizeToFit, NO, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, borderWidth);
    CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
    CGContextSetFillColorWithColor(context, backgroundColor.CGColor);

 CGFloat width = sizeToFit.width, height = sizeToFit.height;
    CGContextMoveToPoint(context, width - halfBorderWidth, radius + halfBorderWidth); // 準(zhǔn)備開始移動(dòng)坐標(biāo)
    CGContextAddArcToPoint(context, width - halfBorderWidth, height - halfBorderWidth, width - radius - halfBorderWidth, height - halfBorderWidth, radius);
    CGContextAddArcToPoint(context, halfBorderWidth, height - halfBorderWidth, halfBorderWidth, height - radius - halfBorderWidth, radius); // 左下角角度
    CGContextAddArcToPoint(context, halfBorderWidth, halfBorderWidth, width - halfBorderWidth, halfBorderWidth, radius); // 左上角
    CGContextAddArcToPoint(context, width - halfBorderWidth, halfBorderWidth, width - halfBorderWidth, radius + halfBorderWidth, radius);
    CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

之后用繪畫出來的image生成imageView栓辜,并將其插入到view的最底層

- (void)dr_addCornerRadius:(CGFloat)radius
           borderWidth:(CGFloat)borderWidth
       backgroundColor:(UIColor *)backgroundColor
          borderCorlor:(UIColor *)borderColor {
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[self dr_drawRectWithRoundedCornerRadius:radius borderWidth:borderWidth backgroundColor:backgroundColor borderCorlor:borderColor]];
    [self insertSubview:imageView atIndex:0];
}

** 之后在你需要圓角的地方就可以放心的調(diào)用此方法了 **

給UIImageVIew繪畫圓角-裁邊處理恋拍,如下

- (UIImage*)dr_imageAddCornerWithRadius:(CGFloat)radius andSize:(CGSize)size{
    CGRect rect = CGRectMake(0, 0, size.width, size.height);

    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
    CGContextAddPath(ctx,path.CGPath);
    CGContextClip(ctx);
    [self drawInRect:rect];
    CGContextDrawPath(ctx, kCGPathFillStroke);
    UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

示例代碼CornerRadius中還對(duì)這些核心方法進(jìn)行了簡(jiǎn)單的封裝,可以下載下來再仔細(xì)的看看藕甩。

聲明:如果你覺得該文章對(duì)有一點(diǎn)點(diǎn)幫助施敢,請(qǐng)移步到iOS 高效添加圓角效果實(shí)戰(zhàn)講解中點(diǎn)贊,該文章的最初想法來自于該大大bestswifter的這篇博文辛萍。并且該大大bestswifter用swift實(shí)現(xiàn)了所有的核心代碼悯姊。本文使用的全部是OC。

參考大大們的文章
iOS 高效添加圓角效果實(shí)戰(zhàn)講解

接下來會(huì)介紹使用Core Animation的UI的調(diào)試方法贩毕,歡迎一起討論


喜歡請(qǐng)隨意


圖片發(fā)自簡(jiǎn)書App
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悯许,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辉阶,更是在濱河造成了極大的恐慌先壕,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谆甜,死亡現(xiàn)場(chǎng)離奇詭異垃僚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)规辱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門谆棺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罕袋,你說我怎么就攤上這事改淑。” “怎么了浴讯?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵朵夏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我榆纽,道長(zhǎng)仰猖,這世上最難降的妖魔是什么捏肢? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮饥侵,結(jié)果婚禮上鸵赫,老公的妹妹穿的比我還像新娘。我一直安慰自己爆捞,他們只是感情好奉瘤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著煮甥,像睡著了一般盗温。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上成肘,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天卖局,我揣著相機(jī)與錄音,去河邊找鬼双霍。 笑死砚偶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洒闸。 我是一名探鬼主播染坯,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼丘逸!你這毒婦竟也來了单鹿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤深纲,失蹤者是張志新(化名)和其女友劉穎仲锄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體湃鹊,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡儒喊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了币呵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀愧。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖余赢,靈堂內(nèi)的尸體忽然破棺而出掸驱,到底是詐尸還是另有隱情,我是刑警寧澤没佑,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站温赔,受9級(jí)特大地震影響蛤奢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一啤贩、第九天 我趴在偏房一處隱蔽的房頂上張望待秃。 院中可真熱鬧,春花似錦痹屹、人聲如沸章郁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暖庄。三九已至,卻和暖如春楼肪,著一層夾襖步出監(jiān)牢的瞬間培廓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國打工春叫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肩钠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓暂殖,卻偏偏與公主長(zhǎng)得像价匠,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呛每,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354