SwiftUI:动画过渡
Posted
技术标签:
【中文标题】SwiftUI:动画过渡【英文标题】:SwiftUI: Animate Transitions 【发布时间】:2021-07-15 22:39:45 【问题描述】:如何在不同视图之间设置幻灯片过渡动画?
在下面的示例代码中,我创建了一个 Picker,用于选择要显示的视图,我的目标是获得一个看起来类似于 NavigationLink 转换的转换。
目前它根本没有动画。
如果我将 .animation(.easeInOut(duration: 2))
修饰符添加到 ZStack
,它会为淡入淡出动画设置 2 秒的动画,但我不明白为什么。
struct ContentView: View
enum WhichScreen: String, CaseIterable
case red, blue, green, yellow
@State private var whichScreen = WhichScreen.red
var body: some View
VStack
Picker("screen", selection: $whichScreen.animation())
ForEach(WhichScreen.allCases, id: \.self) value in
Text(value.rawValue).tag(value)
.pickerStyle(SegmentedPickerStyle())
ZStack
Color.black
switch whichScreen
case .red:
Color.red
case .blue:
Color.blue
case .green:
Color.green
case .yellow:
Color.yellow
.transition(.slide)
【问题讨论】:
【参考方案1】:您真的需要黑色的 ZStack(在您的示例 sn-p 中永远不可见)吗?没有它,转换开箱即用(在模拟器中,而不是在 SwiftUI 预览中):
struct ContentView: View
enum WhichScreen: String, CaseIterable
case red, blue, green, yellow
@State private var whichScreen = WhichScreen.red
var body: some View
VStack
Picker("screen", selection: $whichScreen.animation())
ForEach(WhichScreen.allCases, id: \.self) value in
Text(value.rawValue).tag(value)
.pickerStyle(SegmentedPickerStyle())
Group
switch whichScreen
case .red:
Color.red
case .blue:
Color.blue
case .green:
Color.green
case .yellow:
Color.yellow
.transition(.slide)
【讨论】:
是的,没错。在我的特定用例中,我将所有这些都放在另一个视图之上,在这种情况下,您的代码仅在使用.transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
修饰符时才能按需要工作。但这实际上是更简单的解决方案。谢谢。【参考方案2】:
要获得您正在寻找的幻灯片动画,需要将.transition
应用于您想要滑动的部分(例如,在这种情况下为非黑色):
ZStack
Color.black
Group
switch whichScreen
case .red:
Color.red
case .blue:
Color.blue
case .green:
Color.green
case .yellow:
Color.yellow
.transition(.slide)
如果您希望它与NavigationLink
转换完全一样,您仍然需要多做一步,这就是现在,“旧”或“以前”视图在转换之前消失的事实。如果您希望将其包含在堆栈中,您可以执行以下操作:
struct ContentView: View
enum WhichScreen: String, CaseIterable
case red, blue, green, yellow
@State private var whichScreen = WhichScreen.red
@State private var previousScreen : WhichScreen? = .none
var body: some View
VStack
Picker("screen", selection: $whichScreen.animation())
ForEach(WhichScreen.allCases, id: \.self) value in
Text(value.rawValue).tag(value)
.pickerStyle(SegmentedPickerStyle())
.onChange(of: whichScreen) [whichScreen] _ in
previousScreen = whichScreen
ZStack
Color.black
if let previousScreen = previousScreen
switch(previousScreen)
case .red:
Color.red
case .blue:
Color.blue
case .green:
Color.green
case .yellow:
Color.yellow
Group
switch whichScreen
case .red:
Color.red
case .blue:
Color.blue
case .green:
Color.green
case .yellow:
Color.yellow
.transition(.slide)
【讨论】:
太棒了!非常感谢你!我刚刚注意到过渡在预览中不起作用。我不知道我是否可以再次信任预览版。以上是关于SwiftUI:动画过渡的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 过渡动画在 GeoReader 中不起作用?