Reputation: 30401
I am attempting to create a rounded-rectangle progress indicator in my app. I have previously implemented a circular indicator, but not like this shape. I would like it to look something like this (start point is at the top):
But I get this with 0
as the .strokeStart
property of the layer:
My current code place in viewDidLoad()
:
let queueShapeLayer = CAShapeLayer()
let queuePath = UIBezierPath(roundedRect: addToQueue.frame, cornerRadius: addToQueue.layer.cornerRadius)
queueShapeLayer.path = queuePath.cgPath
queueShapeLayer.lineWidth = 5
queueShapeLayer.strokeColor = UIColor.white.cgColor
queueShapeLayer.fillColor = UIColor.clear.cgColor
queueShapeLayer.strokeStart = 0
queueShapeLayer.strokeEnd = 0.5
view.layer.addSublayer(queueShapeLayer)
addToQueue
is the button which says 'Upvote'.
Unlike creating a circular progress indicator, I cannot set the start and end angle in the initialisation of a Bezier path.
How do I make the progress start from the top middle as seen in the first image?
Edit - added a picture without corner radius on:
It seems that the corner radius is creating the issue.
If you have any questions, please ask!
Upvotes: 1
Views: 1093
Reputation: 30401
I found a solution so the loading indicator works for round corners:
let queueShapeLayer = CAShapeLayer()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Queue timer
let radius = addToQueue.layer.cornerRadius
let diameter = radius * 2
let totalLength = (addToQueue.frame.width - diameter) * 2 + (CGFloat.pi * diameter)
let queuePath = UIBezierPath(roundedRect: addToQueue.frame, cornerRadius: radius)
queueShapeLayer.path = queuePath.cgPath
queueShapeLayer.lineWidth = 5
queueShapeLayer.strokeColor = UIColor.white.cgColor
queueShapeLayer.fillColor = UIColor.clear.cgColor
queueShapeLayer.strokeStart = 0.25 - CGFloat.pi * diameter / 3 / totalLength // Change the '0.25' to 0.5, 0.75 etc. wherever you want the bar to start
queueShapeLayer.strokeEnd = queueShapeLayer.strokeStart + 0.5 // Change this to the value you want it to go to (in this case 0.5 or 50% loaded)
view.layer.addSublayer(queueShapeLayer)
}
After I had did this though, I was having problems that I couldn't animate the whole way round. To get around this, I created a second animation (setting strokeStart
to 0
) and then I placed completion blocks so I could trigger the animations at the correct time.
Tip:
Add animation.fillMode = CAMediaTimingFillMode.forwards
& animation.isRemovedOnCompletion = false
when using a CABasicAnimation
for the animation to wait until you remove it.
I hope this formula helps anyone in the future!
If you need help, you can always message me and I am willing to help. :)
Upvotes: 2