自 Xcode 16 起,只要在垂直
DragGesture
内有水平 ScrollView
的子视图,就会在子视图上检测到水平拖动手势,但不会检测到任何向上/向下滚动。这是一个不会滚动但会识别水平手势的示例代码。
.gesture(DragGesture())
和 .highPriorityGesture(DragGesture())
都不起作用。
ScrollView {
ForEach(item in listOfItems) {
HStack {
Text(item)
Spacer()
}
.padding()
.gesture(DragGesture()
.onChanged { gesture in
let width = gesture.translation.width
print("Current Translation: \(width)")
// do something
}
.onEnded { _ in
// do something
})
}
}
编辑:这也发生在
List
。
我尝试使用
.simultaneousGesture(DragGesture())
,但它会导致 DragGesture
与 TapGesture
同时被识别,这不是理想的行为。
只有在 Xcode 16 上构建应用程序时才会注意到这个特殊问题。它不影响在 iOS 18 上运行的基于 Xcode 15 构建的旧版本。
我在苹果开发者论坛上找到了一个线程讨论了这个问题,但没有建议修复。
我在
minimumDistance
中尝试了不同的 DragGesture()
值,似乎直到 minimumDistance: 15
的值都无法正常工作。
DragGesture
的文档如下:
@MainActor @preconcurrency
init(
minimumDistance: CGFloat = 10,
coordinateSpace: some CoordinateSpaceProtocol = .local
)
因此,SwiftUI 6/Xcode 16 中的
ScrollView
很可能具有类似的检测“滚动”的阈值。在 SwiftUI 的早期版本中,似乎 ScrollView
的阈值始终低于 DragGesture
的默认值。
以下代码片段(带有
minimumDistance: 20.0
)似乎适用于我的用例。我也尝试过minimumDistance: 15.0
,但它似乎是在滚动或拖动之间随机选择。
ScrollView {
LazyVStack {
ForEach(item in listOfItems) {
HStack {
Text(item)
Spacer()
}
.padding()
.gesture(
DragGesture(minimumDistance: 20.0)
.onChanged {
gesture in
let width = gesture.translation.width
print("Current Translation: \(width)")
// do something
}
.onEnded {
_ in
// do something
}
)
}
}
}
注意: 使用
simultaneousGesture
也可以,但需要正确处理 TapGesture
。如果操作不正确,Tap
和 Drag
将同时触发。