Home > Software engineering >  How to disable transition animation when reduce motion is turned off
How to disable transition animation when reduce motion is turned off

Time:09-21

There's a view in my app called ContinueView that slides out of sight when a button is clicked and it works like so:

struct ContentView: View {
    @Environment(\.accessibilityReduceMotion) var isReducedMotion
    @State private var hasRequestedNotifications    = UserDefaults.standard.bool(forKey: "hasRequestedNotifications")
    @State private var isShowingContinueView        = !UserDefaults.standard.bool(forKey: "isLoggedIn")
    
    var body: some View {
     .........

        if (isShowingContinueView) {
            ContinueView(isShowingContinueView: $isShowingContinueView).transition(.asymmetric(insertion: AnyTransition.move(edge: .trailing).combined(with: .opacity), removal:  AnyTransition.move(edge: .leading).combined(with: .opacity)))
        } else if (!hasRequestedNotifications) {
            AllowNotificationsView(hasRequestedNotifications: $hasRequestedNotifications).transition(.asymmetric(insertion: AnyTransition.move(edge: .trailing).combined(with: .opacity), removal:  AnyTransition.move(edge: .leading).combined(with: .opacity)))
        }
     ........
    }
}

ContinueView:

              ....
                Button("Continue") {
                    withAnimation {
                        self.isShowingContinueView.wrappedValue = false
                    }
                }
            .....

This works perfectly, it shows and hides the view with a smooth sliding transition. But for users with reduced motion, I wanted to support it too so that instead of sliding, it just shows and hides with no animation at all.

I've got an enviroment variable at the top of my contentView called: isReducedMotion, with this I want to toggle motion on and off dependent on what the variable is set to.

I've tried putting it like this:

ContinueView(isShowingContinueView: $isShowingContinueView).transition(isReducedMotion ? nil : .asymmetric(insertion: AnyTransition.move(edge: .trailing).combined(with: .opacity), removal:  AnyTransition.move(edge: .leading).combined(with: .opacity)))

But it shows this error: 'nil' cannot be used in context expecting type 'AnyTransition'

So i'm a bit stuck with it and not sure how to get it to work. Does anyone know how to do this? Any help would be really appreciated.

P.S: The code i've put here is modified so its a bit simpler, but yes, the state variables work fine, and the isShowingContinueView variable does get set to true/false elsewhere in the code :)

Also if you have any questions feel free to hit me up since I know my question might be a bit confusing :D

CodePudding user response:

You can try using .identity instead of nil for the transition, or you can pass nil to withAnimation to specify no animation:

Button("Continue") {
    withAnimation(isReducedMotion ? nil : .default) {
        self.isShowingContinueView.wrappedValue = false
    }
}
  • Related