UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: How to fade out a View immediately after it appears

Forums > SwiftUI

I'm working on something similar to the "Subscribed" notice that appears within the Podcast app.

Subscribed notice in Podcasts

struct FloatingNotice: View {
    var body: some View {
        VStack (alignment: .center, spacing: 8) {
            Image(systemName: "checkmark")
                .foregroundColor(.white)
                .font(.system(size: 48, weight: .regular))
                .padding(EdgeInsets(top: 20, leading: 5, bottom: 5, trailing: 5))
            Text("Review added")
                .foregroundColor(.white)
                .font(.callout)
            .padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10))
        }
        .background(Color.snackbar.opacity(0.75))
        .cornerRadius(5)
        .transition(.scale)
        .onAppear {
            withAnimation {
                return self.hidden() // tried self.opacity but that doesn't seem to work either
            }
        }   
    }
}

and I'm presenting my notice from UIKit here

let floatingNotice = UIHostingController(rootView: FloatingNotice())
addChild(floatingNotice)
floatingNotice.view.frame = view.frame
view.addSubview(floatingNotice.view)
floatingNotice.didMove(toParent: self)

I found a pretty simple UIKit way of doing this, but it'd be nice to do this completely from SwiftUI

        UIView.animate(withDuration: 3.0, animations: {
            floatingNotice.view.alpha = 0.0
        }, completion: { success in
            floatingNotice.removeFromParent()
        })

3      

struct ContentView: View {
    @State var showingNotice = false

    var body: some View {
        ZStack {
            Button(action: {
                self.showingNotice = true
            }, label: {
                Text("Show Notice")
            })

            if showingNotice {
                FloatingNotice(showingNotice: $showingNotice)
            }
        }
        .animation(.easeInOut(duration: 1))
    }
}

struct FloatingNotice: View {
    @Binding var showingNotice: Bool

    var body: some View {
        VStack (alignment: .center, spacing: 8) {
            Image(systemName: "checkmark")
                .foregroundColor(.white)
                .font(.system(size: 48, weight: .regular))
                .padding(EdgeInsets(top: 20, leading: 5, bottom: 5, trailing: 5))
            Text("Review added")
                .foregroundColor(.white)
                .font(.callout)
                .padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10))
        }
        .background(Color.snackbar.opacity(0.75))
        .cornerRadius(5)
        .transition(.scale)
        .onAppear(perform: {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
                self.showingNotice = false
            })
        })
    }
}

How about something like this?

3      

Nice that is perfect. Would you have any suggestions on how to remove this from its parent view when the animation finishes?

3      

Here a slightly difference way

Add these two structs to a file

struct FloatingNoticeView: View {
    var body: some View {
        ZStack {

            BlurView()

            VStack {
                Image(systemName: "checkmark")
                    .font(.largeTitle)
                Text("Added")
                    .padding(.top, 8)
            }
            .foregroundColor(.primary)
        }
        .frame(width: 110, height: 110)
        .cornerRadius(10)
    }
}

struct BlurView: UIViewRepresentable {

    func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIVisualEffectView {
        let effect = UIBlurEffect(style: .systemThinMaterialDark)
        let view = UIVisualEffectView(effect: effect)
        return view
    }

    func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<BlurView>) {

    }
}

Then in the view that you want the notice to appear add this

struct ContentView: View {
    @State private var showningFloatingView = false

    var body: some View {
        ZStack {
            Button("Add Review") {
                self.showningFloatingView.toggle()
            }

            if showningFloatingView {
                FloatingNoticeView()
                    .onAppear {
                        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                                self.showningFloatingView.toggle()
                        }
                }
                .animation(.easeInOut)
            }
        }
    }
}

Both remove the view after 2 seconds with DispatchQueue.main.asyncAfter(deadline: .now() + 2)

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.