如何使用终结器制作自定义半循环进度指示器?

时间:2016-04-17 21:55:22

标签: swift calayer cashapelayer

我想制作一个如下所示的自定义半圆倒置进度指示器:

enter image description here

我尝试使用CAShapeLayer作为背景,进度线和进度线终结符(小白圈)。我使用ring.strokeEnd = progress来定义进度行的结束位置。

如何将行终止符添加到进度行的末尾?

这是我的代码(注意:我已经硬编码了小白圈的位置,因为我不知道如何正确实现这一点):

class AKBezierson: UIView {

    var ringBackground: CAShapeLayer!
    var ring: CAShapeLayer!
    var ringTerminator: CAShapeLayer!
    var innerRect: CGRect!
    var radius: CGFloat { return min(innerRect.width, innerRect.height) / 2 }
    var progress: CGFloat  = 0.8 { didSet { updateLayerProperties() } }

    private struct Const {
        static let gap: CGFloat = 10
        static let width: CGFloat = 3.0
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        innerRect = CGRectInset(bounds, Const.width / 2 + Const.gap, Const.width / 2 + Const.gap)

        let path = UIBezierPath()
        path.addArcWithCenter(
            CGPointMake(bounds.width / 2, bounds.height / 2),
            radius: radius,
            startAngle: CGFloat(0),
            endAngle: CGFloat(M_PI),
            clockwise: true)

        if (ringBackground == nil) {
            ringBackground = CAShapeLayer()
            layer.addSublayer(ringBackground)
            ringBackground.path = path.CGPath
            ringBackground.fillColor = nil
            ringBackground.lineWidth = Const.width
            ringBackground.strokeColor = UIColor(white: 1.0, alpha: 0.5).CGColor
        }
        ringBackground.frame = ringBackground.bounds

        if (ring == nil) {
            ring = CAShapeLayer()
            layer.addSublayer(ring)
            ring.path = path.CGPath
            ring.fillColor = nil
            ring.lineWidth = Const.width
            ring.strokeColor = UIColor.whiteColor().CGColor
            ring.strokeEnd = progress
        }
        ring.frame = ring.bounds

        if (ringTerminator == nil) {   // small circle
            ringTerminator = CAShapeLayer()
            layer.addSublayer(ringTerminator)
            let terminatorCircle = UIBezierPath(ovalInRect: CGRectMake(15, 83, 12, 12))
            ringTerminator.path = terminatorCircle.CGPath
            ringTerminator.fillColor = UIColor.whiteColor().CGColor
            ringTerminator.lineWidth = Const.width
            ringTerminator.strokeColor = UIColor.whiteColor().CGColor
        }
        ringTerminator.frame = ringTerminator.bounds

        updateLayerProperties()
    }

    func updateLayerProperties () {
        if !(ring == nil) {
            ring.strokeEnd = progress
        }
    }
}

我还尝试计算进度线结束的点,并在每次进度改变时将线终止符移动到新位置,但我对动画不满意,因为终结器试图到达在最短(海峡)路径之后的新位置。

0 个答案:

没有答案