Reputation: 3054
I have a custom progress view that animates based on Character Count. (similar to twitter)
However, my calculation seems to be off. I want the stroke layer to circle around based on the percentage.
Here's my code:
class CharacterCountView: UIView {
private let progressLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func animateToValue(value: Double) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.toValue = value
animation.duration = 0.5
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
progressLayer.add(animation, forKey: "strokeAnimation")
progressLayer.strokeEnd = value
if value > 1 {
print("100% REACHED")
}
}
}
extension CharacterCountView {
fileprivate func setUpView() {
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(animateToValue)))
let trackLayer = CAShapeLayer()
trackLayer.frame = bounds
let path = UIBezierPath(arcCenter: trackLayer.position, radius: 8, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = path.cgPath
trackLayer.strokeColor = UIColor.systemGray2.cgColor
trackLayer.lineWidth = 1.5
trackLayer.fillColor = Color.background.cgColor
trackLayer.lineCap = .round
layer.addSublayer(trackLayer)
progressLayer.frame = bounds
progressLayer.path = path.cgPath
progressLayer.strokeColor = Color.accent.cgColor
progressLayer.lineWidth = 1.5
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.lineCap = .round
progressLayer.strokeEnd = 0
layer.addSublayer(progressLayer)
}
}
In my Text Did Change Function:
func textDidChange(to value: String) {
if value.isEmpty || value.count > 280 {
postBarButtonItem.isEnabled = false
} else {
postBarButtonItem.isEnabled = true
}
let characterCount = Double(value.count)
let percentage = characterCount / 280
print(percentage)
createPostInputAccessoryView.characterCountView.animateToValue(value: percentage)
}
Its topping out at around 70% what is wrong with my calculation?
Upvotes: 0
Views: 104
Reputation: 77462
Your endAngle
is wrong...
Let's make it a little more "readable":
let path = UIBezierPath(arcCenter: trackLayer.position,
radius: 8,
startAngle: -CGFloat.pi / 2,
endAngle: 2 * CGFloat.pi,
clockwise: true)
This: startAngle: -CGFloat.pi / 2
is minus 90-degrees, or 12 o'clock on the circle.
But this: endAngle: 2 * CGFloat.pi
is 360-degrees, or 3 o'clock
So you have 450-degrees instead of 360-degrees.
I find it helps to use multipliers only, instead of mixing multiplication and division:
let path = UIBezierPath(arcCenter: trackLayer.position,
radius: 8,
startAngle: -CGFloat.pi * 0.5,
endAngle: CGFloat.pi * 1.5,
clockwise: true)
Now we know we're going from minus 90-degrees to 270-degrees ... for 360-degrees total.
Upvotes: 1