iOS圓角view的Swift實現(利用Core Graphics繪製)前端
由於app的列表用用到了圓形圖片的頭像,因此去探究並思考了一下這個問題。首先這個問題有兩個方向的解決方案:git
import UIKit class MaskCornerView: UIView { var cornerRadius: CGFloat = 0.0 var superBackgroundColor = UIColor.white // Only override draw() if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func draw(_ rect: CGRect) { // Drawing code let shortestEdge = min(self.bounds.width, self.bounds.height)//邊長稍短的邊 let radius = max(min((shortestEdge / 2.0), cornerRadius), (shortestEdge / 2.0))//默認半徑爲稍短邊的一半,防止負數或者過大的cornerRadius設置 let context = UIGraphicsGetCurrentContext() //以坐上角爲原點,順時針畫矩形的path context?.move(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY)) context?.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.minY)) context?.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY)) context?.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.maxY)) context?.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY)) context?.closePath() //以左上角往右偏移一個半徑長度的點爲原點,順時針畫圓角矩形 context?.move(to: CGPoint(x: radius, y: self.bounds.minY)) context?.addLine(to: CGPoint(x: (self.bounds.maxX - radius), y: self.bounds.minY)) context?.addArc(tangent1End: CGPoint(x: self.bounds.maxX, y: self.bounds.minY), tangent2End: CGPoint(x: self.bounds.maxX, y: self.bounds.minY + radius), radius: radius) context?.addLine(to: CGPoint(x: self.bounds.maxX, y: (self.bounds.maxY - radius))) context?.addArc(tangent1End: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY), tangent2End: CGPoint(x: self.bounds.maxX - radius, y: self.bounds.maxY), radius: radius) context?.addLine(to: CGPoint(x: radius, y: self.bounds.maxY)) context?.addArc(tangent1End: CGPoint(x: self.bounds.minX, y: self.bounds.maxY), tangent2End: CGPoint(x: self.bounds.minX, y: self.bounds.maxY - radius), radius: radius) context?.addLine(to: CGPoint(x: self.bounds.minX, y: radius)) context?.addArc(tangent1End: CGPoint(x: self.bounds.minX, y: self.bounds.minY), tangent2End: CGPoint(x: radius, y: self.bounds.minY), radius: radius) context?.closePath() context?.setFillColor(superBackgroundColor.cgColor)//設置填充色 context?.fillPath(using: .evenOdd)//設置使用奇偶填充的方式 } override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.clear } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.backgroundColor = UIColor.clear } }
代碼的主要註釋在代碼中已經寫了。下面主要放一張圖展現一下addLine和addArc地方的代碼吧。
開始點移動到P1,畫直線到P2,以P2-P3-P4的圓角舉例,func addArc(tangent1End: CGPoint, tangent2End: CGPoint, radius: CGFloat)
的兩個參數tangent1End爲P3,tangent2End爲P4就能夠畫出這個圓角了(幾指明切線的點)。
上面這個MaskCornerView只須要放到你須要製造圓角的view上,並與之等大小就能夠了能夠配置參數(默認圓形,cornerRadius比較小的時候就是圓角矩形),而且支持IB佈局該MaskCornerView。這樣在重用的cell裏面只是至關於添加了一個view,對性能幾乎沒有啥影響,因此流暢度很高。不信你寫個demo用Instruments看一下就知道了。github
下面再附上我當初是用的裁剪圖片的方式的代碼(添加UIImage的Category就能夠了):objective-c
- (UIImage *)compressToSize:(CGSize)viewsize { CGFloat imgHWScale = self.size.height / self.size.width; CGFloat viewHWScale = viewsize.height/viewsize.width; CGRect rect = CGRectZero; if (imgHWScale>viewHWScale) { rect.size.height = viewsize.width*imgHWScale; rect.size.width = viewsize.width; rect.origin.x = 0.0f; rect.origin.y = (viewsize.height - rect.size.height)*0.5f; } else { CGFloat imgWHScale = self.size.width/self.size.height; rect.size.width = viewsize.height*imgWHScale; rect.size.height = viewsize.height; rect.origin.y = 0.0f; rect.origin.x = (viewsize.width - rect.size.width)*0.5f; } UIGraphicsBeginImageContext(viewsize); [self drawInRect:rect]; UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newimg; } - (UIImage *)circleImage { CGFloat radius = MIN(self.size.width, self.size.height); CGSize size = CGSizeZero; UIImage *squareImage; if (self.size.width == self.size.height) { size = CGSizeMake(self.size.width, self.size.width); squareImage = self; } else { size = CGSizeMake(radius, radius); squareImage = [self compressToSize:CGSizeMake(radius, radius)]; } //1.開啓圖片圖形上下文:注意設置透明度爲非透明 UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); //2.開啓圖形上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); //3.繪製圓形區域(此處根據最小邊來設置) CGFloat x = (self.size.width < self.size.height) ? 0 : ABS(self.size.width - self.size.height) / 2; CGFloat y = (self.size.width < self.size.height) ? ABS(self.size.width - self.size.height) / 2 : 0; CGRect rect = CGRectMake(x, y, radius, radius); CGContextAddEllipseInRect(ref, rect); //4.裁剪繪圖區域 CGContextClip(ref); //5.繪製圖片 [squareImage drawInRect:rect]; //6.獲取圖片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //7.關閉圖形上下文 UIGraphicsEndImageContext(); return image; }
宗旨就是先把圖片弄成正方形的,而後再切圓角。這樣特別麻煩,須要把切圖的過程放到個其它線程裏面,而後圖片切好後再獲取主線程給UIImageView賦值,並且子線程的開銷也比較大。swift
由於此次內容很簡單,就不提供demo了。
參考連接:
[譯]繪製中間鏤空的圖形的方法
iOS設置shadow*帶來的離屏渲染
iOS設置圓角的四種方法app