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