I am trying to achieve a similar effect to the indicator arrow found in iOS's Music app, as you scroll past a certain point it changes from an arrow to a single line. I've attached a slowed down example below.
The point I'm struggling to understand is the arrow itself, I've tried to use two rotated UIView
s as lines positioned together with constraints and have successfully created an animation using UIViewPropertyAnimator
and keyframes. But unfortunately the lines intrude over each other when going from an arrow to line.
I'm unsure of the correct method to achieve this example. Any push in the right direction to achieving this would be highly appreciated.
The simplest way is to animate the path of a CAShapeLayer. This gives you the rounded ends and the mitred join for free. You need a straight path and a bent path; switch from one to the other. The straight path must consist of two segments to match the two segments of the bent path.
Here's my simulation of your animation:
Here's the configuration of the shape layer and its paths:
let shape = CAShapeLayer()
shape.frame = // ...
shape.lineCap = .round
shape.lineJoin = .miter
shape.lineWidth = 6
shape.strokeColor = UIColor.gray.cgColor
shape.fillColor = UIColor.clear.cgColor
let p1 = UIBezierPath()
p1.move(to: CGPoint(x:0, y:35))
p1.addLine(to: CGPoint(x:20, y:35))
p1.addLine(to: CGPoint(x:40, y:35))
let straight = p1.cgPath
let p2 = UIBezierPath()
p2.move(to: CGPoint(x:0, y:25))
p2.addLine(to: CGPoint(x:20, y:30))
p2.addLine(to: CGPoint(x:40, y:25))
let bent = p2.cgPath
Then it's just a matter of alternating the path
of shape
between straight
and bent
as desired.