Menu

Transition

Skip support for SwiftUI.Transition.

The following example screens and source code is from SkipUI’s Showcase sample app TransitionPlayground.swift

import SwiftUI

struct TransitionPlayground: View {
    @State var count = 0

    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                HStack {
                    Text("Default")
                    Spacer()
                    ZStack {
                        if count % 2 == 1 {
                            Color.red
                                .frame(width: 20, height: 20)
                                .id(1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".animation")
                    Spacer()
                    ZStack {
                        if count % 2 == 1 {
                            Color.red
                                .frame(width: 20, height: 20)
                                .id(1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                Button("withAnimation") {
                    withAnimation { updateCount() }
                }
                .buttonStyle(.bordered)
                HStack {
                    Text("HStack.animation")
                    Spacer()
                    HStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("VStack.animation")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("ZStack.animation")
                    Spacer()
                    ZStack {
                        if count > 0 {
                            Color.red
                                .frame(width: 60, height: 60)
                                .id(1)
                        }
                        if count > 1 {
                            Color.green
                                .frame(width: 40, height: 40)
                                .id(2)
                        }
                        if count > 2 {
                            Color.blue
                                .frame(width: 20, height: 20)
                                .id(3)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.move(edge: .top))")
                    Spacer()
                    HStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.move(edge: .top))
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.offset)")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.offset(x: 100, y: 100))
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.opacity)")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.opacity)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.push(from: .top))")
                    Spacer()
                    HStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.push(from: .top))
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.scale)")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.scale)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text(".transition(.slide)")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.slide)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("Asymmetric: opacity+slide")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.asymmetric(insertion: .opacity, removal: .slide))
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("Combined: opacity+slide")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.opacity.combined(with: .slide))
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("Slow spring")
                    Spacer()
                    VStack {
                        ForEach(0..<count, id: \.self) { i in
                            Color.red
                                .frame(width: 20, height: 20)
                                .transition(.slide)
                                .id(i + 1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.spring(duration: 1), value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                HStack {
                    Text("Nested views")
                    Spacer()
                    ZStack {
                        if count % 2 == 1 {
                            VStack {
                                Color.red
                                    .frame(width: 20, height: 20)
                                    .transition(.slide)
                                    .id(1)
                                if count % 2 == 1 {
                                    Color.green
                                        .frame(width: 20, height: 20)
                                        .transition(.slide)
                                        .id(2)
                                }
                            }
                            .frame(width: 80, height: 80)
                            .background(.white)
                            .transition(.opacity)
                            .id(1)
                        }
                    }
                    .frame(width: 100, height: 100)
                    .background(.gray)
                    .animation(.default, value: count)
                    .onTapGesture {
                        updateCount()
                    }
                }
                Button("withAnimation") {
                    withAnimation { updateCount() }
                }
                .buttonStyle(.bordered)
            }
            .padding()
        }
        .toolbar {
            PlaygroundSourceLink(file: "TransitionPlayground.swift")
        }
    }

    private func updateCount() {
        count += 1
        if count > 3 {
            count = 0
        }
    }
}