如何正确使用matchedGeometry?

Mar*_*kon 5 swiftui

当我使用匹配的几何视图修改器时,我总是收到警告

Multiple inserted views in matched geometry group Pair<String, ID>(first: "id1", second: SwiftUI.Namespace.ID(id: 8)) have isSource: true, results are undefined.

虽然动画仍然有效,但我想了解为什么会收到此警告以及如何解决此问题。

这是我构建的动画,任何想法如何摆脱警告?

在此处输入图片说明

使用以下代码

struct ContentView: View {
    @State var details = false
    @Namespace var animation
    
    var body: some View {
        ZStack {
            HStack {
                Rectangle()
                    .frame(width: 100, height: 100)
                    .matchedGeometryEffect(id: "id1", in: animation)
                    .onTapGesture {
                        withAnimation {
                            details.toggle()
                        }
                    }
                
                
                Spacer()
            }
            .zIndex(1)
            
            if details == true {
                AnotherView(details: $details, animation: animation)
                    .zIndex(2)
            }
        }
    }
}


struct AnotherView: View {
    @Binding var details: Bool
    var animation: Namespace.ID
    
    var body: some View {
        ZStack {
            Color.red
            
            Rectangle()
                .frame(width: 300, height: 300)
                .matchedGeometryEffect(id: "id1", in: animation)
                .onTapGesture {
                    withAnimation {
                        details.toggle()
                    }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

vac*_*ama 8

问题是你同时在屏幕上有两个视图(即使第二个覆盖了第一个,第一个仍然存在)。用.matchedGeometryEffect一个视图在逻辑上替换另一个视图,因此在绘制第二个视图时需要删除第一个视图。您可以通过仅绘制第一个Rectanglewhen来解决此问题!details

此外,我将 移动.matchedGeometryEffectRectangles的第一个修饰符以获得更清晰的效果。

struct ContentView: View {
    @State var details = false
    @Namespace var animation
    
    var body: some View {
        ZStack {
            HStack {
                if !details {
                    Rectangle()
                        .matchedGeometryEffect(id: "id1", in: animation)
                        .frame(width: 100, height: 100)
                        .onTapGesture {
                            withAnimation {
                                details.toggle()
                            }
                        }
                }
                
                
                Spacer()
            }
            .zIndex(1)
            
            if details {
                AnotherView(details: $details, animation: animation)
                    .zIndex(2)
            }
        }
    }
}


struct AnotherView: View {
    @Binding var details: Bool
    var animation: Namespace.ID
    
    var body: some View {
        ZStack {
            Color.red
            
            Rectangle()
                .matchedGeometryEffect(id: "id1", in: animation)
                .frame(width: 300, height: 300)
                .onTapGesture {
                    withAnimation {
                        details.toggle()
                    }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

.matchedGeometryEffect文档的状态(加粗加):

如果在同一个事务中插入一个视图,而另一个具有相同键的视图被删除,系统将在窗口空间中插入它们的框架矩形,以使其看起来有一个视图从其旧位置移动到其新位置。通常的过渡机制定义了在过渡期间如何渲染两个视图中的每一个(例如淡入/淡出、缩放等),matchedGeometryEffect() 修饰符只安排要链接的视图的几何形状,而不是它们的渲染。

如果 isSource = true 的组中当前插入的视图数量不完全是一个,则结果未定义,因为不清楚哪个是源视图。


在模拟器中演示

  • 有趣的是,我用 if-else 分隔了我的代码,就像这样,但我仍然遇到与该操作相同的错误。 (3认同)