Reputation: 1009
A bit confused as to why this code does not work as expected.
Some generic animatable view:
struct SomeAnimatableView: View, Animatable {
var percent: Double
var body: some View {
GeometryReader { geo in
ZStack {
Rectangle()
.fill(Color.blue)
.frame(height: 120)
Rectangle()
.fill(Color.red)
.frame(width: geo.size.width * CGFloat(self.percent), height: 116)
}
.frame(width: geo.size.width, height: geo.size.height)
}
}
var animatableData: Double {
set { percent = newValue }
get { percent }
}
}
A view which wraps said animatable view:
struct ProgressRectangle: View {
@Binding var percent: Double
var body: some View {
SomeAnimatableView(percent: percent)
}
}
Finally another view, consider it parent:
struct ContentView: View {
@State var percent: Double
var body: some View {
VStack {
ProgressRectangle(percent: $percent.animation())
Text("Percent: \(percent * 100)")
}
.onTapGesture {
self.percent = 1
}
}
}
Issue ⚠️ why doesn't the progress animate? $percent.animation()
isn't that supposed cause animations? Lots of questions...
A fix 💡:
.onTapGesture {
withAnimation {
self.percent = 1
}
}
However, this doesn't actually fix the issue or answer the question to why that binding doesn't animate. Because this also seems to animate the entire view, notice the button animating its width in this example:
Thoughts, ideas?
Upvotes: 1
Views: 136
Reputation: 257711
Animation to Binding
is a mechanism to transfer animation inside child so when bound variable is changed internally it would be changed with animation.
Thus for considered scenario ProgressRectangle
would look like
struct ProgressRectangle: View {
@Binding var percent: Double
var body: some View {
SomeAnimatableView(percent: percent)
.onTapGesture {
withAnimation(_percent.transaction.animation) { // << here !!
self.percent = 0 == self.percent ? 0.8 : 0
}
}
}
}
without onTapGesture
in ContentView
(similarly as would you have Toggle
which changes value internally).
Here is working solution. Tested with Xcode 11.4 / iOS 13.4
@State var percent: Double = .zero
var body: some View {
VStack {
ProgressRectangle(percent: $percent)
.animation(.default) // << place here !!
.onTapGesture {
self.percent = self.percent == .zero ? 1 : .zero
}
Text("Percent: \(percent * 100)")
}
}
Upvotes: 2