swiftui - 如何正确使用matchedGeometry?

标签 swiftui

当我使用匹配的几何 View 修改器时,我总是收到警告Multiple inserted views in matched geometry group Pair<String, ID>(first: "id1", second: SwiftUI.Namespace.ID(id: 8)) have isSource: true, results are undefined.虽然动画仍然有效,但我想了解为什么会收到此警告以及如何解决此问题。
这是我构建的动画,任何想法如何摆脱警告?
enter image description here
使用以下代码

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()
                    }
                }
        }
    }
}

最佳答案

问题是你同时在屏幕上有两个 View (即使第二个覆盖了第一个,第一个仍然存在)。使用 .matchedGeometryEffect 一个 View 在逻辑上替换另一个 View ,因此在绘制第二个 View 时需要删除第一个 View 。您可以通过仅在 Rectangle 时绘制第一个 !details 来解决此问题。
此外,我将 .matchedGeometryEffect 移动为 Rectangle 的第一个修饰符以获得更清晰的效果。

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()
                    }
                }
        }
    }
}
.matchedGeometryEffect Documentation 状态(加粗):

If inserting a view in the same transaction that another view with the same key is removed, the system will interpolate their frame rectangles in window space to make it appear that there is a single view moving from its old position to its new position. The usual transition mechanisms define how each of the two views is rendered during the transition (e.g. fade in/out, scale, etc), the matchedGeometryEffect() modifier only arranges for the geometry of the views to be linked, not their rendering.

If the number of currently-inserted views in the group with isSource = true is not exactly one results are undefined, due to it not being clear which is the source view.



demo in simulator

关于swiftui - 如何正确使用matchedGeometry?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64581837/

相关文章:

SwiftUI - 按钮 - 如何将函数(带参数)请求从子传递给父

ios - 如何检测在 onEnded 关闭时是否启动了 sequensed 的第二个手势?

SwiftUI 标题字体

ios - TextField SwiftUI 关闭键盘

ios - 如何在 swiftUI 中呈现 crossDissolve View ?

swiftui - 如何在 macOS 上使用 SwiftUI 显示 QLPreviewPanel?

ios - 如何在 SwiftUI 和 iOS 14 中更改单元格背景颜色?

swift - barButtonItem 中 UIKit 的 "pushViewController"的 SwiftUI 的替代方案是什么

arrays - SwiftUI 从列表中删除行

SwiftUI:如何使图像与列表中的屏幕边缘齐平?