irpas技术客

Swift 圆形进度条_烟花下的孤独_swift 环形进度条

网络投稿 2731

效果图

前言 ios 10.0

因为 UI 做了一些很别致的进度条效果图,而且在网上又找不到合适的三方库,自己在网上查查资料做了出来,然后整理了一下,分享给大家使用

首先,这个东西只是用贝赛尔曲线做出来的,并不是很难,做出来只是略微麻烦一点,网上也有很多资料,不过并不是很多,所以我就整理了一下,一是整理备份一下记录,二是分享给大家看下

1、绘制这个断断续续的进度条

UI 设计很漂亮,但是由于数据过多或过少,导致太难看,最后放弃

1.1 初始化一个贝塞尔直线 ///贝塞尔直线 private lazy var path: UIBezierPath = { let bezierPath = UIBezierPath() bezierPath.move(to: CGPoint(x: 0, y: 0)) bezierPath.addLine(to: CGPoint(x: bounds.size.width, y: 0)) return bezierPath }() 1.2 使用CAShapeLayer初始化底部背景线,和进度线

此处 lineDashPattern 是长度对比,一长一短线,我使用的是两个数据,多个的话,暂时没弄明白,有大佬了解的留个言, 建议:此处进度最好和你自己进度比率相同,要不然会出现上图的情况(一线两色)

///背景线 private lazy var backLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.fillColor = UIColor.clear.cgColor layer.strokeColor = .green.cgColor layer.lineWidth = 2 layer.lineDashPattern = [15, 3] layer.path = path.cgPath return layer }() ///进度条线 private lazy var progressLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.fillColor = UIColor.clear.cgColor layer.strokeColor = .red.cgColor layer.lineWidth = 2 layer.lineDashPattern = [15, 3] layer.strokeStart = 0 layer.strokeEnd = 0 layer.path = path.cgPath return layer }() 1.3 添加到视图上

直接设置 progressLayer.strokeEnd = progress 会显得突兀,我再此添加了一个动画, 后续此处就不一一说明

///数据 layer.addSublayer(backLayer) layer.addSublayer(progressLayer) ///进度 public var progress: CGFloat = 0.0 { didSet { CATransaction.begin() CATransaction.setDisableActions(false) CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) CATransaction.setAnimationDuration(2) progressLayer.strokeEnd = progress CATransaction.commit() } } 2 普通圆形进度条

2.1首先开放公共参数 ///背景颜色 public var backColor: UIColor = .gray ///进度条颜色 public var progressColor: UIColor = .red ///线宽 public var lineWidth: CGFloat = 2.0 ///圆直径 public var realWidth: CGFloat = 100 ///圆起点角度。角度从水平右侧开始为0,顺时针为增加角度。直接传度数 如-90 public var startAngle: CGFloat = 0.5 * .pi ///圆结束角度。角度从水平右侧开始为0,顺时针为增加角度。直接传度数 如-90 public var endAngle: CGFloat = 0.5 * .pi ///动画时长 public var duration: CGFloat = 2 2.2 使用贝赛尔曲线画圆

设置中心点、半径(通过直径 - 宽度计算得来)、起始位置,结束位置

let radius = realWidth / 2 - lineWidth ///贝塞尔直线 private lazy var path: UIBezierPath = { let bezierPath = UIBezierPath(arcCenter: CGPoint(x: realWidth/2, y: realWidth/2), radius: radius, startAngle: startAngle, endAngle: 2 * .pi + endAngle, clockwise: true) return bezierPath }() 2.2 使用CAShapeLayer初始化底部背景线,和进度线

然后 添加到视图,和设置进度我就不说了,上面都有, 至于是多少角度的圆形,设置起始角度和结束角度就可以了

///背景圆环 private lazy var backLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.frame = bounds layer.fillColor = UIColor.clear.cgColor layer.lineWidth = lineWidth layer.strokeColor = backColor.cgColor layer.lineCap = .round layer.path = path.cgPath return layer }() ///进度圆环 private lazy var progressLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.frame = bounds layer.fillColor = UIColor.clear.cgColor layer.lineWidth = lineWidth layer.strokeColor = progressColor.cgColor layer.lineCap = .round layer.path = path.cgPath layer.strokeEnd = 0 return layer }() 3 绘制渐变进度条

3.1首先开放渐变公共参数

相同参数我就不在一一叙述

///渐变颜色 public var colors: [CGColor] = [UIColor.red.cgColor, UIColor.green.cgColor] ///渐变色位置 public var locations: [NSNumber] = [0, 1] ///渐变色起始位置 public var startPoint: CGPoint = CGPoint(x: 0, y: 0) ///渐变色结束位置 public var endPoint: CGPoint = CGPoint(x: 1, y: 0) 3.2 使用CAGradientLayer设置渐变背景 ///渐变背景 private lazy var gradientLayer: CAGradientLayer = { let layer = CAGradientLayer() layer.frame = bounds layer.colors = colors layer.locations = locations layer.startPoint = startPoint layer.endPoint = endPoint return layer }() 3.3 把进度圆环放到渐变背景上

然后加载进度就可以了

gradientLayer.mask = progressLayer layer.addSublayer(gradientLayer) 4 在进度条终点添加样式

4.1 添加终点样式

此处我使用了 UIView,你可以采用图片、渐变 view 等 在 layer.addSublayer(progressLayer) 后面放入,

addSubview(dot) dot.isHidden = true 4.2 跟谁进度条速度加载

使用 CAAnimation 加载动画 整圆和非整圆这块加载我没给弄清楚,有了解的大佬请给予指出,虽然结果没错,但是两套逻辑总感觉很奇怪

private lazy var pointAnimation: CAAnimation = { let animation = CAKeyframeAnimation(keyPath: "position") animation.timingFunction = CAMediaTimingFunction(name: .linear) animation.fillMode = .forwards animation.calculationMode = CAAnimationCalculationMode.paced animation.isRemovedOnCompletion = false animation.duration = duration ///此处记得加载代理,不用执行方法 animation.delegate = self var end = 2 * .pi * progress + startAngle ///非整圆 if data.startAngle != data.endAngle { end = (2 * .pi - CGFloat(fabs(Double(endAngle))) - startAngle) * progress + startAngle } let imagePath = UIBezierPath(arcCenter: CGPoint(x: realWidth/2, y: realWidth/2), radius: radius, startAngle: startAngle, endAngle: end, clockwise: true) animation.path = imagePath.cgPath return animation }()

执行加载动画, 此处跟谁到 progress 设置进度后面即可

dot.isHidden = false dot.layer.add(pointAnimation, forKey: "pointAnimation") 5 仪表盘进度条样式

5.1 公开参数

此处总长度是圆周长长度,这个切记要计算好,否则最后一根线会有问题

///线间距 间断进度条专属 直线计算长度,圆计算周长 public var lineDashPattern: [NSNumber] = [15 , 5] 5.2 初始化贝塞尔曲线,CAShapeLayer背景和进度条 ///贝塞尔直线 private lazy var path: UIBezierPath = { let bezierPath = UIBezierPath(arcCenter: CGPoint(x: data.realWidth / 2, y: data.realWidth / 2), radius: radius, startAngle: startAngle, endAngle: 2 * .pi + endAngle, clockwise: true) return bezierPath }() ///背景 private lazy var backLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.frame = bounds layer.fillColor = UIColor.clear.cgColor layer.lineWidth = lineWidth layer.strokeColor = backColor.cgColor layer.path = cgPath layer.lineDashPattern = lineDashPattern return layer }() ///进度条 private lazy var progressLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.frame = bounds layer.fillColor = UIColor.clear.cgColor layer.lineWidth = lineWidth layer.strokeColor = progressColor.cgColor layer.path = path.cgPath layer.strokeEnd = 0 layer.lineDashPattern = lineDashPattern return layer }()

添加和设置进度和之前一样,我就不一一赘述

下面就说些我封装的进度条使用方法

1、通过设置 type 类型,添加各种类型的进度条

let newView = HJProgress(frame: CGRect(x: 10, y: 110, width: 120, height: 120)) newView.type = .circle

2、通过设置HJData() 设置各种参数,添加数据之后,才会出现进度条

var data = HJData() data.realWidth = 120 data.lineWidth = 2 newView.data = data

3、通过设置progress 加载进度条

demo 传送门

具体例子看我下面 github 的 demo 吧,欢迎来提建议 demo

CSDN 上ZIP 压缩包(免积分) HJProgress


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Swift #环形进度条 #demo #传送门demo效果图前言ios #100因为 #UI