Home > Net >  SwiftUI: 'value' parameter not working as expected in iOS 15's new animation method s
SwiftUI: 'value' parameter not working as expected in iOS 15's new animation method s

Time:03-29

I'm trying to solve the iOS 15's warning: 'animation' was deprecated in iOS 15.0: Use withAnimation or animation(_:value:) instead. in a view that appears on top of screen that looks like push notification alert (or what so called snack bar), but the view loses animation effect when I use any Equatable value in the value parameter, the code for this view is as follows (you can copy & paste it as is to try it out):

import Foundation
import SwiftUI

struct ContentView: View {
    @State private var showSnackBar = false
    
    var body: some View {
        
        ZStack {
            Color.gray
            
            Text("Show Me")
                .padding()
                .onTapGesture {
                    showSnackBar = true
                }
            
            EmptyView()
                .snackBar(title: "this is a test message", show: $showSnackBar)
                .offset(x: 0, y:  50)
        }
        .edgesIgnoringSafeArea(.all)
    }
}


struct SnackBarModifier: ViewModifier {
    var title: String
    @Binding var show: Bool
    @State var task: DispatchWorkItem?
    
    func body(content: Content) -> some View {
        
        ZStack {
            if self.show {
                VStack {
                    HStack {
                        
                        Text(title)
                        
                        Spacer()
                    }
                    .foregroundColor(.white)
                    .padding(12)
                    .background(Color.orange)
                    .cornerRadius(8)
                    
                    Spacer()
                }
                    .frame(maxWidth: UIScreen.main.bounds.width - 40)
                    .animation(.easeInOut(duration: 0.7), value: ...) //<---- this is where I should use the value in order to solve iOS 15 animation deprecation warning
                    .transition(AnyTransition.move(edge: .top)
                        .combined(with: .opacity))
                    
                    .onTapGesture {
                        withAnimation {
                            self.show = false
                        }
                }
                .onAppear {
                    self.task = DispatchWorkItem {
                        withAnimation {
                            self.show = false
                        }
                    }
                    // Auto dismiss after 2 seconds
                    DispatchQueue.main.asyncAfter(deadline: .now()   2, execute: self.task!)
                }
                .onDisappear {
                    self.task?.cancel()
                }
            }
            
            content
        }
        
    }
}

extension View {
    func snackBar(title: String, show: Binding<Bool>) -> some View {
        self.modifier(SnackBarModifier(title: title, show: show))
    }
}

I tried to use a separate boolean state var that is toggled when the self.show is set to true but to no avail, how can I animate the appearance of this snack bar view using easeInOut(duration:) animation using iOS 15's animation style ?

CodePudding user response:

Put animation modifier on top ZStack container, like

struct SnackBarModifier: ViewModifier {
    var title: String
    @Binding var show: Bool
    @State var task: DispatchWorkItem?

    func body(content: Content) -> some View {

        ZStack {
            if self.show {

                // other content ...
            }

            content
        }
        .animation(.easeInOut(duration: 0.7), value: show)  // << here !!
    }
}

Tested with Xcode 13.2 / iOS 15.2

  • Related