【发布时间】:2021-03-06 09:30:36
【问题描述】:
我正在尝试使用 SwiftUI 在我的应用中实现拖放功能。
我创建了两个圆圈,它们位于两个不同的HStacks 中。它们不共享相同的坐标空间。
有笔划的圆圈是目标,绿色的实心圆圈是要拖动的对象。
我能够在.overlay 中使用GeometryReader 获得他们的绝对位置。我用它来检测当对象圆被拖动到目标圆上时它们是否重叠。这行得通。
当它们不重叠时,对象圆将移回其原始位置。当它们重叠时,对象圆应该在目标圆的位置卡入到位。这是我似乎有问题的地方。
我正在尝试通过以下方式设置对象圆的新 X 和 Y 位置: 对象圆局部位置-对象圆全局位置+目标圆全局位置。
objectPosition = CGPoint(
x: objectPosition.x - objectFrame.midX + targetFrame.midX,
y: objectPosition.y - objectFrame.midY + targetFrame.midY
)
我假设这会将我带到目标圆的坐标空间。但不知何故,它不起作用。
到目前为止,我一直无法找到一种可靠且简单的方法来在 SwiftUI 中转换坐标空间。在叠加层内使用GeometryReader 的解决方法至少给了我正确的全局位置。但是我还没有找到一种方法来使用这些位置将视图也放置在.global 坐标空间中。
如果有人知道为什么我对坐标空间的计算是错误的,或者甚至知道一种方法可以更轻松地相互转换和定位视图,我将不胜感激。
这是我的 SwiftUI 单视图 iOS 应用程序代码:
import SwiftUI
struct ContentView: View {
@State private var isDragging: Bool = false
@State private var objectDragOffset: CGSize = .zero
@State private var objectPosition: CGPoint = .zero
@State private var objectFrame: CGRect = .zero
@State private var targetFrame: CGRect = .zero
var body: some View {
VStack {
HStack {
Circle()
.stroke(lineWidth: 3)
.fill(Color.blue)
.frame(width: 100.0, height: 100.0)
.overlay(
GeometryReader { targetGeometry in
Color(.clear)
.onAppear { targetFrame = targetGeometry.frame(in: .global) }
}
)
.position(CGPoint(x:180, y: 190))
}.background(Color.yellow)
HStack {
Circle()
.foregroundColor(.green)
.frame(width: 100, height: 100, alignment: .center)
.overlay(
GeometryReader { objectGeometry in
Color(.clear)
.onAppear {
objectFrame = objectGeometry.frame(in: .global) }
}
)
.position(objectPosition)
.offset( isDragging ? objectDragOffset : .zero)
.onAppear { objectPosition = CGPoint(x: 200, y: 250 ) }
.gesture(
DragGesture(coordinateSpace: .global)
.onChanged { drag in
isDragging = true
objectDragOffset = drag.translation
}
.onEnded { drag in
isDragging = false
if targetFrame.contains(drag.location) {
objectPosition = CGPoint(
x: objectPosition.x - objectFrame.midX + targetFrame.midX,
y: objectPosition.y - objectFrame.midY + targetFrame.midY
)
} else {
objectPosition = CGPoint(x: 200, y: 250 )
}
}
)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
【问题讨论】:
-
经过更多测试,它认为问题可能与覆盖中的
GeometryReader以及覆盖在代码中的位置有关。由于以这种方式使用它是一种解决方法,它似乎要么覆盖工作正常,要么 GeometryReader 取决于它的放置位置和调用 .onAppear 的时间。我正在尝试弄清楚是否是这种情况。
标签: swift swiftui drag-and-drop coordinates geometryreader