我想制作一个如下所示的自定义半圆倒置进度指示器:
我尝试使用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
}
}
}
我还尝试计算进度线结束的点,并在每次进度改变时将线终止符移动到新位置,但我对动画不满意,因为终结器试图到达在最短(海峡)路径之后的新位置。