使用导航链接在视图之间导航时使用匹配几何效果

yam*_*mbo 10 swift swiftui swiftui-navigationlink swiftui-animation swiftui-transition

我的主视图包含CustomView,点击时可通过 来打开详细视图NavigationLink。详细视图还包含CustomView,只是位置不同。

CustomView我可以使用匹配几何效果在单击导航链接时对位置进行过渡/动画吗?

struct HomeView: View {
    @Namespace var namespace
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("Top")
                NavigationLink {
                    DetailView(namespace: namespace)
                } label: {
                    CustomView()
                        .matchedGeometryEffect(id: "testId", in: namespace)
                }
                Text("Bottom")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
struct DetailView: View {
    var namespace: Namespace.ID
    
    var body: some View {
        VStack {
            CustomView()
                .matchedGeometryEffect(id: "testId", in: namespace)
            Text("Details")
            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Cur*_*rge 0

我要说的是,“不,你不能用它来为整个NavigationStack.matchedGeometryEffect转换中的视图位置设置动画。”

一些细节:首先,如果没有动画块,.matchedGeometryEffect 将无法工作。因此,您可以将代码重写为如下所示:

struct HomeView: View {
    @Namespace var namespace
    @State private var showDetail = false
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("Top")
                Button {
                    withAnimation() {
                        showDetail.toggle()
                    }
                } label: {
                    CustomView
                        .matchedGeometryEffect(id: "testId", in: namespace)
                }
                Text("Bottom")
            }
            .navigationDestination(isPresented: $showDetail) {
                DetailView(namespace: namespace)
            }
        }
    }
}

private struct DetailView: View {
    var namespace: Namespace.ID
    
    var body: some View {
        VStack {
            CustomView()
                .matchedGeometryEffect(id: "testId", in: namespace)
            Text("Details")
            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

withAnimation这使您有机会以匹配的几何效果所需的方式使用。然而,你仍然没有得到你想要的动画,这让我得出了上面的结论。

我推测导航转换与普通的 SwiftUI 转换不同。支持这一点的一个线索是,您可以应用于 DetailView 中的内容的任何.transition在转换期间都不会触发。另一个线索是,使用withAnimation(.easeIn(duration: 5))不会给你 5 秒的过渡。

您最好的选择可能是不使用 NavigationStack。只需使用条件(带有动画过渡)即可在两个布局之间切换。我还建议您花几天时间研究Swift UI Lab 网站上的优秀资源,是一个与您特别相关的页面。

我希望这有帮助!