SwiftUI:从屏幕上的 CGPoint 转换为视图中的 CGPoint

问题描述

我在 ContentView 的某处放置了一个视图。我希望能够将图像放到它上面。所以我添加了 .onDrop 到它。在 UIKit 中,我会使用 UniverseView.convert(point,to: targetView)。我如何在 SwiftUI 中执行此操作?

示例实用程序可以是绘制放置在橙色方块上的放置图像的缩略图

struct ContentView: View {
    @State var isTargeted: Bool = false
    
    var body: some View {
        vstack {
            
            Spacer()
                .frame(width: 600,height: 200)
                .background(Color.yellow.opacity(0.3))

            HStack {
                Spacer()
                    .frame(width: 200,height: 200)
                    .background(Color.yellow.opacity(0.3))

                Spacer()
                    .frame(width: 200,height: 200)
                    .background(Color.orange)
                    .onDrop(of: [ "public.image"],isTargeted: $isTargeted,perform: { (providers,point) -> Bool in
                        
                        print(point) // i.e. (x:336.0,y:486.5)
                                     // but I want it in the context of this views frame
                        // let bodyView: View
                        // let targetView: View
                        // let thePoint = bodyView.convert(point,to: targetView)
                        return true
                        
                    })

                Spacer()
                    .frame(width: 200,height: 200)
                    .background(Color.yellow.opacity(0.3))

            }
            .frame(width: 600,height: 200)

            Spacer()
                .frame(width: 600,height: 200)
                .background(Color.yellow.opacity(0.3))
        }
        .frame(width: 600,height: 600)
    }
}

解决方法

extension GeometryProxy {
    // converts from some other coordinate space to the proxy's own
    func convert(_ point: CGPoint,from coordinateSpace: CoordinateSpace) -> CGPoint {
        let frame = self.frame(in: coordinateSpace)
        let localViewPoint = CGPoint(x: point.x-frame.origin.x,y: point.y-frame.origin.y)
        
        // Some system bug? Test in iOS 13.4,13.5,14.1,14.5
        if coordinateSpace == .global {
            switch (UIDevice.current.systemVersion as NSString).floatValue {
            case 13.5:
                return CGPoint(x: localViewPoint.x,y: point.y)
            case 14.5:
                return point
            default: break
            }
        }
        
        return localViewPoint
    }
}

像这样使用:geometry.convert(location,from: .global)