skip to Main Content

I have the following code:

struct ContentView: View {
    
    @State var show = false
    
    var body: some View {
        
        VStack {
            
            ZStack {
                
                Color.black
                
                if show {
                    RoundedRectangle(cornerRadius: 20)
                        .fill(.brown)
                        .transition(.opacity)
                }
                
            }
            
            Button {
                withAnimation(.easeInOut(duration: 1)) {
                    show.toggle()
                }
            } label: {
                Text("TRIGGER")
            }

        }

    }
    
}

I want the RoundedRectangle to fade in and out. Right now it only fades in. This is a simplified version of a more complex view setup I have. Depending on the state I may have the view I want to fade in or not. So, I am looking for a way to fade in (like it works now) but then also fade out so that the view is totally removed from the hierarchy and not just hidden or something.

How can I have this code also fade OUT the view and not only fade in?

As a reference I followed this approach:

https://swiftui-lab.com/advanced-transitions/

....
if show {
    LabelView()
         .animation(.easeInOut(duration: 1.0))
         .transition(.opacity)
    }
        
    Spacer()
        
    Button("Animate") {
        self.show.toggle()
    }.padding(20)
....

But, in my case it is NOT fading out.

2

Answers


  1. You need to link the opacity directly to the state, so that it is directly animating any changes.

    struct ContentView: View {
          @State var show = false
       
       var body: some View {
          VStack {
             ZStack {
                Color.black
                (RoundedRectangle(cornerRadius: 20)
                   .fill(.brown)
                   .opacity(show ? 1 : 0)
                )
             }
             
             Button {
                withAnimation(.easeInOut(duration: 1)) {
                   show.toggle()
                }
             } label: {
                Text("TRIGGER")
             }
          }
       }
    }
    

    EDIT: to reflect the comment requiring the view to be removed, not just faded out…

    To remove the view (and trigger .onDisappear) you could modify as below:

             ZStack {
                Color.black
                show ? (RoundedRectangle(cornerRadius: 20)
                   .fill(.brown)
                   .zIndex(1).  //kudos to @aheze for this!
    
                ).onDisappear{print("gone")}
                : nil
             }
    

    This will fade in/out as above, but will actually remove the view & print "gone"

    Login or Signup to reply.
  2. SwiftUI ZStack transitions are finicky. You need to add a zIndex to make sure the hierarchy is preserved, enabling the animation.

    RoundedRectangle(cornerRadius: 20)
        .fill(.brown)
        .transition(.opacity)
        .zIndex(1) /// here!
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search