zumzum
zumzum

Reputation: 20278

SwiftUI: fade out view

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.

Upvotes: 4

Views: 6410

Answers (2)

flanker
flanker

Reputation: 4210

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"

Upvotes: 1

aheze
aheze

Reputation: 30584

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!

Upvotes: 9

Related Questions