在SwiftUI中,我们使用NavigationView
和NavigationLink
视图来执行导航(在segue
中我们曾称UIKit
为导航)。 UIKit中的标准segue是show
segue。在SwiftUI中,我们可以简单地执行以下操作:
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: Text("Destination")) {
Text("Navigate!")
}
}
}
}
}
具有完全相同的效果(即使单词segue
已经消失)。
有时(实际上是经常),我们需要自定义segue动画。
Animates
协议的对象来完成的。所有的魔术都发生在UIViewControllerAnimatedTransitioning
方法中,该方法使我们可以访问源视图控制器和目标视图控制器。例如,简单的淡入淡出segue动画可能类似于:
animateTransition
现在的问题是:如何在SwiftUI中获得相同的内容?是否可以不对导航设置动画或自定义导航动画?我希望能够做到:
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
UIView* containerView = [transitionContext containerView];
UIViewController* fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController* toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
toVC.view.alpha = 0;
[containerView addSubview:toVC.view];
[UIView animateWithDuration:1 animations:^{
toVC.view.alpha = 1;
fromVC.view.alpha = 0;
} completion:^(BOOL finished) {
[fromVC.view removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
或类似的阻止动画(或添加自定义动画)的东西,但没有任何变化。
答案 0 :(得分:8)
不幸的是,仍然无法在SwiftUI(xCode 11.3.1)中自定义NavigationView
过渡动画。
寻找一种解决方法,我最终创建了一个名为swiftui-navigation-stack
(https://github.com/biobeats/swiftui-navigation-stack)的开源项目,其中包含NavigationStackView
,该视图模仿了标准的导航行为NavigationView
添加了一些有用的功能。例如,您可以关闭转场动画,也可以使用自己喜欢的转场自定义它们。
一个月前,我在上面问过如何关闭过渡动画。为此,您可以通过以下方式使用NavigationStackView
:
struct ContentView : View {
var body: some View {
NavigationStackView(transitionType: .none) {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
PushView(destination: View2()) {
Text("PUSH")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
PopView {
Text("POP")
}
}
}
}
如果将.none
指定为transitionType
,则可以关闭动画。 PushView
和PopView
是两个视图,允许您推送和弹出视图(类似于SwiftUI NavigationLink
)。
结果是:
相反,如果您想自定义过渡动画(如我在上面的问题中使用淡入淡出示例所问的那样),您可以这样做:
struct ContentView : View {
let navigationTransition = AnyTransition.opacity.animation(.easeOut(duration: 2))
var body: some View {
NavigationStackView(transitionType: .custom(navigationTransition)) {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
PushView(destination: View2()) {
Text("PUSH")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
PopView {
Text("POP")
}
}
}
}
对于交叉转换,我指定了:
let navigationTransition = AnyTransition.opacity.animation(.easeOut(duration: 2))
持续2秒的淡入淡出过渡。然后,我将此转换传递到NavigationStackView
:
NavigationStackView(transitionType: .custom(navigationTransition))