Search code examples
swiftanimationswiftuiios14

View don't disappear with the way it should


I am trying to make the yellow views disappear from bottom and top with a nice and smooth animation. (slide/move to top/bottom + fadding and keep the middle view taking the whole space) This is my current state, and it is everything but smooth and nice haha. but it works.

import SwiftUI

struct ContentView: View {
    @State var isInterfaceHidden: Bool = false

    var body: some View {
        VStack(spacing: 0, content: {
            if !isInterfaceHidden {
                Rectangle()
                    .id("animation")
                    .foregroundColor(Color.yellow)
                    .frame(height: 40)
                    .transition(AnyTransition.move(edge: .top).combined(with: .opacity).animation(.linear))
            }
            Rectangle()
                .id("animation2")
                .foregroundColor(Color.red)
                .transition(AnyTransition.opacity.animation(Animation.linear))
                /// We make sure it won't cover the top and bottom view.
                .zIndex(-1)
                .background(Color.red)
                .onTapGesture(perform: {
                    DispatchQueue.main.async {
                        self.isInterfaceHidden.toggle()
                    }
                })
            if !isInterfaceHidden {
                Rectangle()
                    .id("animation3")
                    .foregroundColor(Color.yellow)
                    .frame(height: 80)
                    .transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(.linear))
            }
        })
        .navigationBarTitle("")
        .navigationBarHidden(true)
    }
}

Current animation:

current animation

Edit3: Thanks to @Andrew I was able to progress in a better state. But now I have a sort of jerky animation. Any thoughts?


Solution

  • I may have found a solution for you:

    import SwiftUI
    
    struct ContentView: View {
        @State var isInterfaceHidden: Bool = false
    
        var body: some View {
            VStack(spacing: 0, content: {
                if !isInterfaceHidden {
                    Rectangle()
                        .id("animation")
                        .foregroundColor(Color.yellow)
                        .frame(height: 40)
                        .transition(.topViewTransition)
                }
                Rectangle()
                    .id("animation2")
                    .foregroundColor(Color.red)
                    /// We make sure it won't cover the top and bottom view.
                    .zIndex(-1)
                    .background(Color.red)
                    .onTapGesture(perform: {
                        DispatchQueue.main.async {
                            self.isInterfaceHidden.toggle()
                        }
                    })
                if !isInterfaceHidden {
                    Rectangle()
                        .id("animation3")
                        .foregroundColor(Color.yellow)
                        .frame(height: 80)
                        .transition(.bottomViewTransition)
                }
            })
            .navigationBarTitle("")
            .navigationBarHidden(true)
            .animation(.easeInOut)
        }
    }
    
    extension AnyTransition {
    
        static var topViewTransition: AnyTransition {
            let transition = AnyTransition.move(edge: .top)
                .combined(with: .opacity)
            return transition
        }
    
        static var bottomViewTransition: AnyTransition {
            let transition = AnyTransition.move(edge: .bottom)
                .combined(with: .opacity)
            return transition
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }