如图,这个动画的是如何做的呢?
分析:
- 1.环形进度指示器,根据下载进度来更新它
- 2.扩展环,向内向外扩展这个环,中间扩展的时候,去掉这个遮盖
一.环形进度指示器
1.自定义View继承UIView,命名为CircularLoaderView.swift,此View将用来保存动画的代码
2.创建CAShapeLayer
1 2 |
let circlePathLayer = CAShapeLayer() let circleRadius: CGFloat = 20.0 |
3.初始化CAShapeLayer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 两个初始化方法都调用configure方法 override init(frame: CGRect) { super.init(frame: frame) configure() } required init?(coder aDecoder: NSCoder) { super.init(coder : aDecoder) configure() } // 初始化代码来配置这个shape layer: func configure(){ circlePathLayer.frame = bounds; circlePathLayer.lineWidth = 2.0 circlePathLayer.fillColor = UIColor.clearColor().CGColor circlePathLayer.strokeColor = UIColor.redColor().CGColor layer.addSublayer(circlePathLayer) backgroundColor = UIColor.whiteColor() // 初始化属性,后面用来监听图片下载进度 progress = 0.0 } |
4.设置环形进度条的矩形frame
1 2 3 4 5 6 7 |
// 小矩形的frame func circleFrame() -> CGRect { var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius) circleFrame.origin.x = CGRectGetMidX(circlePathLayer.bounds) - CGRectGetMidX(circleFrame) circleFrame.origin.y = CGRectGetMidY(circlePathLayer.bounds) - CGRectGetMidY(circleFrame) return circleFrame } |
可以参考下图,理解这个circleFrame
5.每次自定义的这个view的size改变时,你都需要重新计算circleFrame,所以要将它放在一个独立的方法,方便调用
1 2 3 4 |
// 通过一个矩形(正方形)绘制椭圆(圆形)路径 func circlePath() -> UIBezierPath { return UIBezierPath(ovalInRect: circleFrame()) } |
6.由于layers没有autoresizingMask这个属性,你需要在layoutSubviews方法中更新circlePathLayer的frame来恰当地响应view的size变化
1 2 3 4 5 6 |
override func layoutSubviews() { super.layoutSubviews() circlePathLayer.frame = bounds circlePathLayer.path = circlePath().CGPath } |
7.给CircularLoaderView.swift文件添加一个CGFloat
类型属性,自定义的setter和getter方法,setter方法验证输入值要在0到1之间,然后赋值给layer的strokeEnd属性。