如何在SwiftUI中将@namespace传递给多个视图?

时间:2020-07-28 09:07:47

标签: swiftui ios14 xcode12

我正在使用新的Xcode 12 beta和SwiftUi 2.0。 .matchedGeometryEffect()修饰符非常适合制作Hero动画。 SwiftUI中引入了一个新属性@Namespace。它超级酷。工作很棒。

我只是想知道是否有可能将命名空间变量传递给多个视图?

这是我正在研究的示例,

struct HomeView: View {
    @Namespace var namespace
    @State var isDisplay = true
    
    var body: some View {
        ZStack {
            if isDisplay {
                VStack {
                    Image("share sheet")
                        .resizable()
                        .frame(width: 150, height: 100)
                        .matchedGeometryEffect(id: "img", in: namespace)
                    Spacer()
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color.blue)
                .onTapGesture {
                    withAnimation {
                        self.isDisplay.toggle()
                    }
                }
            } else {
                VStack {
                    Spacer()
                    Image("share sheet")
                        .resizable()
                        .frame(width: 300, height: 200)
                        .matchedGeometryEffect(id: "img", in: namespace)
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color.red)
                .onTapGesture {
                    withAnimation {
                        self.isDisplay.toggle()
                    }
                }
            }
        }
    }
}

一切正常。

但是如果我想将Vstack提取为子视图,则下图显示我已将第一个VStack提取到了子视图中。

enter image description here

我得到了称赞 Cannot find 'namespace' in scope

是否可以在多个视图之间传递名称空间?

1 个答案:

答案 0 :(得分:12)

@NamaspaceNamaspace.ID的包装,您可以将Namaspace.ID的参数传递给子视图。

这里是可能解决方案的演示。经过Xcode 12 / iOS 14的测试

struct HomeView: View {
    @Namespace var namespace
    @State var isDisplay = true

    var body: some View {
        ZStack {
            if isDisplay {
                View1(namespace: namespace, isDisplay: $isDisplay)
            } else {
                View2(namespace: namespace, isDisplay: $isDisplay)
            }
        }
    }
}

struct View1: View {
    let namespace: Namespace.ID
    @Binding var isDisplay: Bool
    var body: some View {
        VStack {
            Image("plant")
                .resizable()
                .frame(width: 150, height: 100)
                .matchedGeometryEffect(id: "img", in: namespace)
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.blue)
        .onTapGesture {
            withAnimation {
                self.isDisplay.toggle()
            }
        }
    }
}

struct View2: View {
    let namespace: Namespace.ID
    @Binding var isDisplay: Bool
    var body: some View {
        VStack {
            Spacer()
            Image("plant")
                .resizable()
                .frame(width: 300, height: 200)
                .matchedGeometryEffect(id: "img", in: namespace)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.red)
        .onTapGesture {
            withAnimation {
                self.isDisplay.toggle()
            }
        }
    }
}