I'm trying to make my custom segmented control. With UI and functionality I'm ok but I've some problems with animations.
I want that white circle moves to new tapped value with a fluid animation perhaps stretching and then returning to a circle once the right position is reached.

struct SegmentedControl: View{
@State var position: RotationCase = .P1
var body: some View {
ZStack {
HStack {
ForEach(RotationCase.allCases, id: \.self) { rcase in
Text(rcase.rawValue)
.foregroundColor(rcase == position ? .black : .white)
.padding()
.background(rcase == position ? .white : .black)
.clipShape(Circle())
.onTapGesture {
withAnimation {
position = rcase
}
}
}
}
}
.frame(height: 45)
.padding(10)
.background(.black)
.clipShape(Capsule())
.shadow(radius: 8)
}
}
enum RotationCase:String, CaseIterable {
case P1 = "P1", P2 = "P2" , P3 = "P3" , P4 = "P4" , P5 = "P5" , P6 = "P6"
}
Did you have a solution or a tutorial ref for this kind of animations?
I am going to preface my answer by pointing you to a wonderful post on creating an animating shapes: Blob, the Builder - A Step by Step Guide to SwiftUI Animation that does a great job of creating a shape and animating it. However, in the end, what he created was a
Capsule()into which he could send inputs to change the size. That seemed a bit of overkill when we can do essentially the same thing with aCapsule()and a.frame().The other thing I wanted to avoid was a
GeometryReader. I like them and use them, but used incorrectly things can go sideways pretty quickly. This answer is all computed with just one spacer and one capsule each in its own frame underneath of the buttons. The code is commented below.