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 } }}