很早就想寫一篇講述圓角優(yōu)化的博客了炕矮。簇宽。結(jié)果發(fā)現(xiàn)這篇文章iOS 高效添加圓角效果實(shí)戰(zhàn)講解寫得很好:摘錄文章的總結(jié)部分勋篓,當(dāng)拓展閱讀了:
總結(jié)
如果能夠只用 cornerRadius 解決問(wèn)題,就不用優(yōu)化魏割。
如果必須設(shè)置 masksToBounds譬嚣,可以參考圓角視圖的數(shù)量,如果數(shù)量較少(一頁(yè)只有幾個(gè))也可以考慮不用優(yōu)化钞它。
UIImageView 的圓角通過(guò)直接截取圖片實(shí)現(xiàn)拜银,其它視圖的圓角可以通過(guò) Core Graphics 畫出圓角矩形實(shí)現(xiàn)。
過(guò)早的優(yōu)化是惡魔遭垛,這句話確實(shí)很有道理
Premature optimization is the root of all evil --Donald Knuth
當(dāng)時(shí)我做圓角優(yōu)化的場(chǎng)景尼桶,是一個(gè)collectionView很多頭像的展示。如果單純的用layer設(shè)置cornerRadius和masksToBounds锯仪,會(huì)產(chǎn)生離屏渲染泵督,小心別讓圓角成了你列表的幀數(shù)殺手,這篇文章已經(jīng)寫的很清楚了庶喜,就不贅述了小腊。
self.xxView.layer.cornerRadius = 5.0f;
self.xxView.layer.masksToBounds = YES;
Advanced Graphics and Animations for iOS Apps(session 419) 學(xué)習(xí)與延伸這篇文章也介紹了離屏渲染的一些知識(shí),有需要的同學(xué)可以去拓展閱讀一下久窟。
正文
其實(shí)寫到這里我已經(jīng)很方了秩冈。。因?yàn)楦杏X(jué)好多人都寫過(guò)了斥扛。入问。
這邊再留兩篇文章:
最早接觸到圓角優(yōu)化是里脊串寫的一次對(duì)MKMapView的性能優(yōu)化
近來(lái)還有葉孤城___的reviewcode.cn里提出的解決方案。
你們可以先看我的文章稀颁,然后再去拓展閱讀芬失,反正上面那么多鏈接你們也要看一會(huì)[認(rèn)真臉]。
既然原理上面的文章都講過(guò)很多了匾灶,我真不好意思再講一遍了麸折,我就來(lái)說(shuō)說(shuō)我怎么做的吧。
首先給imageView一個(gè)catagory粘昨,核心方法如下:
- (void)lhy_loadImageUrlStr:(NSString *)urlStr placeHolderImageName:(NSString *)placeHolderStr radius:(CGFloat)radius;
當(dāng)然也有些簡(jiǎn)便的方法方便不同場(chǎng)景調(diào)用:
- (void)lhy_loadImageUrlStr:(NSString *)urlStr;
- (void)lhy_loadImageUrlStr:(NSString *)urlStr radius:(CGFloat)radius;
核心方法是這樣寫的:
- (void)lhy_loadImageUrlStr:(NSString *)urlStr placeHolderImageName:(NSString *)placeHolderStr radius:(CGFloat)radius {
//something
//這里有針對(duì)不同需求的處理,我就沒(méi)貼出來(lái)了
//...
NSURL *url;
if (placeHolderStr == nil) {
placeHolderStr = @"你通用的占位圖地址";
}
//這里傳CGFLOAT_MIN窜锯,就是默認(rèn)以圖片寬度的一半為圓角
if (radius == CGFLOAT_MIN) {
radius = self.frame.size.width/2.0;
}
url = [NSURL URLWithString:urlStr];
if (radius != 0.0) {
//頭像需要手動(dòng)緩存處理成圓角的圖片
NSString *cacheurlStr = [urlStr stringByAppendingString:@"radiusCache"];
UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:cacheurlStr];
if (cacheImage) {
self.image = cacheImage;
}
else {
[self sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:placeHolderStr] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (!error) {
UIImage *radiusImage = [UIImage createRoundedRectImage:image size:self.frame.size radius:radius];
self.image = radiusImage;
[[SDImageCache sharedImageCache] storeImage:radiusImage forKey:cacheurlStr];
//清除原有非圓角圖片緩存
[[SDImageCache sharedImageCache] removeImageForKey:urlStr];
}
}];
}
}
else {
[self sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:placeHolderStr] completed:nil];
}
}
圓角的繪制方法是一個(gè)imageView的catagory
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,
float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0)
{
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM(context, ovalWidth, ovalHeight);
fw = CGRectGetWidth(rect) / ovalWidth;
fh = CGRectGetHeight(rect) / ovalHeight;
//根據(jù)圓角路徑繪制
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
+ (id)createRoundedRectImage:(UIImage*)image size:(CGSize)size radius:(NSInteger)r
{
int w = size.width;
int h = size.height;
UIImage *img = image;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
//CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, w, h);
CGContextBeginPath(context);
addRoundedRectToPath(context, rect, r, r);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
img = [UIImage imageWithCGImage:imageMasked];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageMasked);
return img;
}
這樣只要兩個(gè)catagory张肾,這個(gè)頭像圓角結(jié)合SDWebImage緩存的應(yīng)用場(chǎng)景,就可以即插即用啦锚扎。
簡(jiǎn)書已經(jīng)棄用吞瞪,歡迎移步我的小專欄:
https://xiaozhuanlan.com/dahuihuiiOS