The setup is quite simple:
- State/Observable/Computet property, let's call it
S1
- Views (
V1
,V2
) that depend onS1
The following conditions must hold:
V1
should have a transition for in/out and be animated- Other views (e.g.
V2
) must not be animated whenS1
changes V2
is animatable by other states (e.g.S2
)
Some consequences:
- Using
withAnimation { .. }
onS1
would also lead to animatingV2
unless animation is disabled here using.animation(nil)
. - However,
V2.animation(nil)
is not an option, because they still need to be animatable by the other state variableS2
. - I therefore ruled out
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!
CodePudding user response:
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 !!