Reputation: 1088
I have a SheetAnimationView
from which I want to show a sheet called SheetContentView
.
When the sheet appears, I want to show a transition animation of its content (start the animation when the content appears) but am unable to make it work. All 3 views in VStack should ideally end their animation at the same time.
SheetContentView:
struct SheetContentView: View {
@Binding var showSheet: Bool
var body: some View {
VStack(spacing: 8) {
Text("A great content of my new sheet")
Label("still not done", systemImage: "guitars")
Text("I'm done now")
}
.transition(.asymmetric(insertion: .scale, removal: .opacity)) // <--- I want this to work
.animation(Animation.easeInOut(duration: 2)) // <--- for 2 seconds
}
}
SheetAnimationView:
struct SheetAnimationView: View {
@State var showSheet: Bool = false
var body: some View {
Button("show my sheet with animated content (hopefully)") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetContentView(showSheet: $showSheet)
}
}
}
Upvotes: 2
Views: 5361
Reputation: 1368
Adding alternative way of using onAppear
so you don't need to nest all views within if
block. (Same result as gif in other answer)
struct SheetContentView: View {
@State var scale = 0.0
@State var opacity = 0.0
var body: some View {
VStack(spacing: 8) {
Text("A great content of my new sheet")
Label("still not done", systemImage: "guitars")
Text("I'm done now")
}
.scaleEffect(scale)
.opacity(opacity)
.onAppear {
withAnimation(.easeInOut(duration: 1)) {
scale = 1.0
opacity = 1.0
}
}
}
}
struct SheetAnimationView: View {
@State var showSheet: Bool = false
var body: some View {
Button("show my sheet with animated content (hopefully)") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetContentView()
}
}
}
Upvotes: 0
Reputation: 257533
Transition works when view is appeared in view hierarchy (not on screen), so to solve this we need another container and state.
Here is a fixed variant. Tested with Xcode 12.1 / iOS 14.1
struct SheetContentView: View {
@Binding var showSheet: Bool
@State private var isShown = false
var body: some View {
VStack { // container to animate transition !!
if isShown {
VStack(spacing: 8) {
Text("A great content of my new sheet")
Label("still not done", systemImage: "guitars")
Text("I'm done now")
}
.transition(.asymmetric(insertion: .scale, removal: .opacity))
}
}
.animation(Animation.easeInOut(duration: 2))
.onAppear {
isShown = true // << activate !!
}
}
}
Upvotes: 3