The setup is quite simple:
S1
V1
, V2
) that depend on S1
The following conditions must hold:
V1
should have a transition for in/out and be animatedV2
) must not be animated when S1
changesV2
is animatable by other states (e.g. S2
)Some consequences:
withAnimation { .. }
on S1
would also lead to animating V2
unless animation is disabled here using .animation(nil)
.V2.animation(nil)
is not an option, because they still need to be animatable by the other state variable S2
.withAnimation { .. }
I prepared the following example:
struct Test: View {
@State private var S1: Bool = false
@State private var S2: Bool = false
func VX(_ text: String, color: Color = .red) -> some View {
Text(text).padding(10).background(color).padding(10)
}
var transition: AnyTransition {
.move(edge: .top).combined(with: .opacity)
}
var body: some View {
VStack {
if S1 {
VX("V1")
.transition(transition)
.animation(.easeOut, value: S1) // <--- not working
}
VX("V2", color: S2 ? .red : .blue)
.offset(x: S1 ? 30 : 0)
Spacer()
HStack {
Button(action: changeS1) {
Text("Change S1")
}
Button(action: changeS2) {
Text("Change S2")
}
}
}
}
func changeS1() {
S1.toggle()
}
func changeS2() {
S2.toggle()
}
}
I think they way I implement the animation doesn't work because the view is conditionally inserted by the same variable and thus not present at the time where the value (S1
) is changing thus .animation(.., value: S1)
cannot detect any changes and thus no animation occurs.
So the question is: How to animate a view's transition based on a variable that determines it's conditional presence at the same time?
Any ideas are appreciated - thanks!
The .animation
modifier should be applied to a container owning conditional view, so it could animate appear/disapper transition, like
VStack {
if S1 {
VX("V1")
.transition(transition)
}
// ... other code
}
.animation(.easeOut, value: S1) // < here !!