Jakob
Jakob

Reputation: 13

How do I implement a custom transition for a View in SwiftUI

I am trying to implement a transition that makes my view move in from the side an disappear by getting smaller. Apple already provides some Transitions but how can I customize this transitions? P.S. I am using the .transition modifier.

Upvotes: 0

Views: 1960

Answers (2)

superpuccio
superpuccio

Reputation: 12972

I'd like to point out that there's a bug about the transition animations. You are supposed to be able to get what you want this way:

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

    private var slideAndScale: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
        let removal = AnyTransition.scale
        return .asymmetric(insertion: insertion, removal: removal)
    }

    var body: some View {
        ZStack {
            Color.green
            if showView {
                Color.yellow
                    .transition(slideAndScale)
            }            
            Button(action: {
                withAnimation {
                    self.showView.toggle()
                }
            }) {
                self.showView ? Text("HIDE VIEW") : Text("SHOW VIEW")
            }
        }
    }
}

Where the Color.yellow is the view that navigates in and out with the custom animation. But if you copy-paste this code you'll find out that the removal animation (in this case the scale animation) won't work. And this is a bug of SwiftUI. To solve this issue there's a workaround:

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

    private var slideAndScale: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
        let removal = AnyTransition.scale
        return .asymmetric(insertion: insertion, removal: removal)
    }

    var body: some View {
        ZStack {
            Color.green
            VStack {
                if showView {
                    Color.yellow
                        .transition(slideAndScale)
                }
            }
            Button(action: {
                withAnimation {
                    self.showView.toggle()
                }
            }) {
                self.showView ? Text("HIDE VIEW") : Text("SHOW VIEW")
            }
        }
    }
}

embed the if showView block in a VStack and the removal animation will behave as expected.

Upvotes: 0

Prydwen
Prydwen

Reputation: 541

You can make a computed variable of the type AnyTransition as follows:

static var moveAndFade: AnyTransition {
    let insertion = AnyTransition.move(edge: .trailing)
        .combined(with: .opacity)
    let removal = AnyTransition.scale
        .combined(with: .opacity)
    return .asymmetric(insertion: insertion, removal: removal)
}

You might wanna check out the tutorial series by Apple

Upvotes: 2

Related Questions