首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在SwiftUI中动画化视图之间的转换?

如何在SwiftUI中动画化视图之间的转换?
EN

Stack Overflow用户
提问于 2020-03-21 05:10:14
回答 1查看 8.9K关注 0票数 15

我有以下看法。

代码语言:javascript
复制
import SwiftUI

struct AppView: View {
    @EnvironmentObject var appStore: AppStore

    var body: some View {
        ZStack {
            Color.blue

            if .game == self.appStore.appMode {
                GameView()
            } else if .options == self.appStore.appMode {
                OptionsView()
            } else {
                MenuView()
            }
        }
    }
}

我想动画在子视图之间的切换。我已经看到了一些例子,使用一个状态为一个开关,但我依赖不止一个。我还尝试使用onAppearonDisappear在子视图中应用动画。这是可行的,但是当视图没有显示时,onDisappear就不再被执行了。此外,我想让它适用于所有的观点。

在不使用多个状态的情况下,有办法做到这一点吗?我希望只使用.transition.animation

现在我最好的解决办法就是这个。

代码语言:javascript
复制
import SwiftUI

struct AppView: View {
    @EnvironmentObject var appStore: AppStore

    var body: some View {
        ZStack {
            Color.blue

            if .game == self.appStore.appMode {
                GameView()
                .transition(.scale)
                .zIndex(1) // to keep the views on top, however this needs to be changed when the active child view changes.
            } else if .options == self.appStore.appMode {
                OptionsView()
                .transition(.scale)
                .zIndex(2)
            } else {
                MenuView()
                .transition(.scale)
                .zIndex(3)
            }
        }
    }
}

上,每个视图改变器。

代码语言:javascript
复制
.onTapGesture {
    withAnimation(.easeInOut(duration: 2)) {
        self.appStore.appMode = .game
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-21 08:27:47

使用以下方法,您可以根据自己的意愿修改appMode (onAppear、onTapGesture等)。当然,动画的持续时间可以任意设置(实际上,也可以设置某种转换,但是某些转换在预览中表现不佳,应该在模拟器或实际设备上进行测试)。

演示:(第一次眨眼只是预览启动,然后是onAppear的两个过渡,然后是onTap)

测试用Xcode 11.4 / iOS 13.4 -工作,在预览和模拟器。

代码:使用内联注释标记的重要部件。

代码语言:javascript
复制
var body: some View {
    ZStack {
        // !! to keep background deepest, `cause it affects removing transition
        Color.blue.zIndex(-1)

        // !! keep any view in explicit own `if` (don't use `else`)
        if .game == self.appStore.appMode {
            GameView()
                .transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
        }

        if .options == self.appStore.appMode {
            OptionsView()
                .transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
        }

        if .menu == self.appStore.appMode {
            MenuView()
                .transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
        }
    }
}

更新:用于.slide(可能还有其他移动的转换)状态的变化应该包装成显式的withAnimation,如下所示

代码语言:javascript
复制
withAnimation {
    self.appStore.appMode = new_mode_here
}

注意:这是模拟器中的预览测试不支持的转换之一.

转换的例子,如

代码语言:javascript
复制
    ...
    if .menu == self.appStore.appMode {
        Text("MenuView").frame(width: 300, height: 100).background(Color.red)
            .transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(.easeInOut(duration: 1)))
    }
}
.onTapGesture {
    withAnimation {
        let next = self.appStore.appMode.rawValue + 1
        self.appStore.appMode = next > 2 ? .game : AppStore.AppMode(rawValue: next)!
    }
}

票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60784673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档