У меня есть круговой UIBezierPath и 2x CAShapeLayers, которые я использую для отображения прогресса в достижении определенной вехи в одном из моих приложений.
Проблема: когда я анимирую прогресс с помощью CABasicAnimation, прогресс выходит за рамки того, что он должен делать.
Контекст: я показываю этот круговой вид в подпредставлении настраиваемой ячейки внутри своего вида milestonesCollectionView.
Иерархия представления: CollectionView> Custom Cell> subview> drawRect, чтобы создать и добавить туда слои.
Мой код:
Пользовательская ячейка
Внутри моей пользовательской ячейки я настраиваю currentProgress (на данный момент жестко запрограммирован для целей тестирования)
let placeHolderForProgressView: CircularTrackerView = {
let ctv = CircularTrackerView()
ctv.backgroundColor = UIColor.clear
ctv.translatesAutoresizingMaskIntoConstraints = false
ctv.currentProgress = 0.5 //set to 0.5 to get a circle filled at 50%
return ctv
}()
Внутри CircularTrackerView
// Я анимирую прогресс всякий раз, когда ячейка установлена, и предоставляю currentProgress для progressView
var currentProgress: CGFloat = 0.0 {
didSet {
animate(to: currentProgress)
let percent = Int(currentProgress * 100)
percentLbl.text = "\(percent)%"
}
}
let shapeLayer = CAShapeLayer() //displays the progress
let trackLayer = CAShapeLayer() //background of the ring
override func draw(_ rect: CGRect) {
super.draw(rect)
let center = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.white.withAlphaComponent(0.2).cgColor
trackLayer.lineWidth = 5
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = kCALineCapRound
layer.addSublayer(trackLayer)
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = UIColor.white.cgColor
shapeLayer.lineWidth = 5
shapeLayer.strokeEnd = 0
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineCap = kCALineCapRound
layer.addSublayer(shapeLayer)
}
private func animate(to progress: CGFloat) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0.0
animation.toValue = progress
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
shapeLayer.add(animation, forKey: "randomString")
}
Вывод
Круг выходит за отметку 50% ... даже сложно, я думаю, что выполнил правильные шаги, чтобы создать это (немного адаптировано из учебника LetsBuildThatApp на YouTube: https://www.youtube.com/watch?v=O3ltwjDJaMk)
Заранее спасибо, если вы можете внести свой вклад, который может помочь.