I created a SampleView
where a Button
is wrapped in a ZStack
, and the whole ZStack
is animated on tap of the Button
. It looks like below:
struct SampleView: View {
@State private var toggle: Bool = false
var body: some View {
ZStack {
Button {
toggle.toggle()
} label: {
Text("Tap here to move!")
.font(.system(size: 20, weight: .black))
.foregroundColor(.black)
}
.padding(10)
.background(.red)
}
.offset(x: 0, y: toggle ? 0 : 200)
.animation(.easeInOut(duration: 1), value: toggle)
}
}
struct SampleView_Previews: PreviewProvider {
static var previews: some View {
// ZStack {
SampleView()
// }
}
}
There’s a bunch of other views that I want to present, so I simply wrapped SampleView
inside a VStack
(or ZStack
). Now, the animation started to break:
struct SampleView_Previews: PreviewProvider {
static var previews: some View {
ZStack {
SampleView()
}
}
}
I noticed that I can work around this behavior by wrapping the button action with withAnimation
.
withAnimation(.easeInOut(duration: 1)) {
toggle.toggle()
}
Still, I wonder what’s going on here. Is this a bug?
2
Answers
This certainly looks like a bug. The
Text
label of the button is not getting the.animation()
value applied to it, but the background is.Here is another way to fix it. Apply the
.animation()
modifier to theText
label as well:More Evidence of the Bug
In this example, we have two buttons in a
VStack
that move together. This works correctly in iOS 15.5, but it breaks in iOS 16. The animation breaks for the button that is being pressed, but it works for the other button.The same fixes apply here: add the
.animation()
modifier to theText
label of each button, or wrap the button action withwithAnimation { }
.I think it’s a bug too. I found a temporary workaround.
You can try
onTapGesture
.I fixed the weird animation.