- 设置:**
我正在将应用程序从UIKit转换为SwiftUI。
应用程序现在使用SwiftUI Map
而不是MKMapView
。
不幸的是,苹果并没有为Map
提供MKMapView
的所有功能,例如拖动Map注解和获取拖动终点的坐标。
无论如何,我正尝试在SwiftUI中实现一个类似的函数。这是我的注解视图的开发主体:
var body: some View {
GeometryReader { geo in // 1
let frameInGlobal = geo.frame(in: .global)
Image("PinRed")
.background(Color.green) // 2
.offset(CGSize(width: dragAmount.width, height: dragAmount.height - liftOff)) // 3
.defersSystemGestures(on: .all) // 4
.onTapGesture {
print("Global center: \(frameInGlobal.midX) x \(frameInGlobal.midY)")
}
.gesture(drag(frameInGlobal: frameInGlobal)) // 5
.simultaneousGesture( // 6
LongPressGesture(minimumDuration: 0.2)
.onEnded { _ in // 7
liftOff = 40.0
}
)
}
.frame(width: 30, height: 30)
.background(Color.red) // 2
}
<1>GeometryReader
用于在拖动过程中获取屏幕坐标。
<2>背景颜色在那里,以便它可以很容易地识别发生了什么。
<3>大头针图像偏移拖动量加上垂直位移,以便大头针在手指上方可见。
<4>系统手势(例如双击后放大和长按以拖动Map)被推迟,以便自定义手势通过。
<5>自定义拖动手势实质上会更改@GestureState var dragAmount = CGSize.zero
,以便大头针图像跟随手指。
<6>需要simultaneousGesture
,以便可以使用自定义点击手势和自定义长按手势。
<7>销被提离,表示可以开始拖动。
- 问题:**
如果liftOff
的值是0.0
,我可以点击注解,它会打印出它的位置,我可以长按它并四处拖动它。拖动停止后,它仍然接受进一步的点击和长按。
然而,当liftOff
值为40.0
时,注解只能在不拖动的情况下点击,并且当第一次拖动注解时,不能再次拖动。这意味着自定义手势不再出现。相反,只有系统手势起作用。
以下是第一次拖动后的情况示例(绿色为图像背景,红色为GeometryReader
背景)。
- 问题:**
为什么自定义手势只在大头针没有被提起时才被接受?
怎么做才对?
- 编辑:**
我刚刚发现,只要Image
**(绿色方块)和GeometryReader
(红色方块)重叠,并且点击点、长按点和拖动的起点都在重叠区域内,我的自定义手势就可以工作。
1条答案
按热度按时间fae0ux8s1#
问题解决,与SwiftUI无关:
如果在上面的代码示例中
liftOff
为0
,则绿色的View
(Image
)和红色的View
(GeometryReader
)在屏幕上始终具有相同的位置。如果点击绿色View
,则点击位置将转发到自定义手势。由于红色View
在屏幕上具有相同的位置,红色的View
处理命中。然而,如果
liftOff
大于绿色View
和红色View
的frame
大小,则两者在屏幕上不重叠。如果现在轻击绿色View
,则命中位置被转发到不与绿色View
重叠的红色View
,即红色View
未被命中。并且该命中被转发到绿色View
之后的下一个View
,该View
是Map
本身,因此不触发定制手势,而是触发系统手势。在上面的代码中,通过添加第3行作为
GeometryReader
的最后一个视图修饰符,可以很容易地检查这一点。