はじめに
先日、SwiftUIのAnimationとTransitionについて学習しました。
AnimationとTransitionの組み合わせによって挙動が変わったり、
Transition自身もcombineして組み合わせることができるといったように
柔軟な設定が可能なのですがその分わかりにくいです。
今回はAnimationとTransitionの組み合わせを実機で試すことができるアプリを作りました。
作ったもの
TransitionとcombineするTransition、及び付与するAnimationを
インサート時とリムーバル時それぞれ設定して挙動を確認することが可能です。
コード
下記を丸っとコピーして実行します。
かなり殴り書きなコードですが、springのdurationなども指定できるように今後改良していきたいと思います。
Contentview.swift
import SwiftUI
struct ContentView: View {
@State private var viewFlg: Bool = false
@State private var isResume: Bool = false
private let transitionList: [AnyTransition] = [.slide, .opacity, .scale, .move(edge: .top), .move(edge: .leading), .move(edge: .bottom), .move(edge: .trailing)]
private let transitionStringList: [String] = ["slide", "opacity",
"scale", "move(edge: .top)", "move(edge: .leading)", "move(edge: .bottom)", "move(edge: .trailing)"]
private let animationList: [Animation] = [.default, .linear, .easeIn, .easeOut, .easeInOut, .spring(response: 0.5, dampingFraction: 0.5, blendDuration: 1), .interactiveSpring(response: 0.5, dampingFraction: 0.5, blendDuration: 0.5)]
private let animationStringList: [String] = [".default", ".linear", ".easeIn", ".easeOut", ".easeInOut", ".spring()", ".interactiveSpring()"]
@State private var insertAnimationSelection: Int = 0
@State private var removalAnimationSelection: Int = 0
@State private var insertSelection: Int = 0
@State private var removalSelection: Int = 0
@State private var insertCmbSelection: Int = 0
@State private var removalCmbSelection: Int = 0
@State private var insertCombineFlg: Int = 0
@State private var removalCombineFlg: Int = 0
var body: some View {
VStack {
ZStack {
Color.white
// こいつにtransitionを反映する
if viewFlg || !isResume {
Rectangle()
.fill(Color.blue)
.frame(width: 100, height: 40)
.transition(.asymmetric(
insertion: insertCombineFlg == 0 ? transitionList[self.insertSelection] : transitionList[self.insertSelection].combined(with: transitionList[self.insertCmbSelection])
,removal: removalCombineFlg == 0 ? transitionList[self.removalSelection] : transitionList[self.removalSelection].combined(with: transitionList[self.removalCmbSelection])))
.zIndex(2)
}
VStack {
Spacer()
HStack {
Spacer()
if !isResume {
Button(action: {
self.isResume.toggle()
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) {timer in
withAnimation(animationList[self.insertAnimationSelection]) {
self.viewFlg.toggle()
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) {timer in
withAnimation(animationList[self.removalAnimationSelection]) {
self.viewFlg.toggle()
}
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) {timer in
self.isResume.toggle()
}
}
}
}
}, label: {
Image(systemName: "play.circle")
.resizable()
.frame(height: 40)
.frame(width: 40)
})
}
}
}
.padding()
.zIndex(1)
}
.frame(height: 200)
NavigationView {
VStack {
Form {
Picker("", selection: self.$insertCombineFlg) {
Text("single").tag(0)
Text("combine").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Picker(selection: $insertSelection, label: Text("InsertTransition"), content: {
ForEach(0 ..< transitionStringList.count) { num in
Text(self.transitionStringList[num])
}
})
if self.insertCombineFlg == 1 {
Picker(selection: $insertCmbSelection, label: Text("withTransition"), content: {
ForEach(0 ..< transitionStringList.count) { num in
Text(self.transitionStringList[num])
}
})
}
Picker(selection: $insertAnimationSelection, label: Text("Animation"), content: {
ForEach(0 ..< animationStringList.count) { num in
Text(self.animationStringList[num])
}
})
}
Form {
Picker("", selection: self.$removalCombineFlg) {
Text("single").tag(0)
Text("combine").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Picker(selection: $removalSelection, label: Text("removalAnimation"), content: {
ForEach(0 ..< transitionStringList.count) { num in
Text(self.transitionStringList[num])
}
})
if self.removalCombineFlg == 1 {
Picker(selection: $removalCmbSelection, label: Text("withTransition"), content: {
ForEach(0 ..< transitionStringList.count) { num in
Text(self.transitionStringList[num])
}
})
}
Picker(selection: $removalAnimationSelection, label: Text("Animation"), content: {
ForEach(0 ..< animationStringList.count) { num in
Text(self.animationStringList[num])
}
})
}
} .navigationBarHidden(true)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
