SwiftUI:取消父视图上的 TapGesture
Posted
技术标签:
【中文标题】SwiftUI:取消父视图上的 TapGesture【英文标题】:SwiftUI: Cancel TapGesture on parent view 【发布时间】:2020-01-28 09:57:08 【问题描述】:我在 SwiftUI 中有视图层次结构,例如
ParentView
//other views
ChildView().highPriorityGesture(TapGesture().onEnded
print("Tap!")
)
// other views
self.gesture(tap)
并且我想让父视图处理屏幕上的所有点击,尽管用户点击了 ChildView。现在两个闭包都执行了。 如何停止点击手势事件向上传播视图层次结构?
【问题讨论】:
有点糊涂……那你为什么不想处理highPriorityGesture
到ChildView
呢?
如果点击在子视图矩形上方,我不想让父视图识别手势。父视图覆盖整个屏幕前列表和子视图只是此列表中的单元格。尽管有这个单个子视图单元格,但我想在整个屏幕上被点击识别。我考虑添加较高优先级的手势块较低优先级的手势,但它不能以这种方式工作。
【参考方案1】:
嗯,可能有一些具体的确切位置是 ChildView
和 ParentView
,因为如下所示(Xcode 11.2 / ios 13.2)子视图手势只是覆盖了父视图手势。
这里是演示......点击黄色区域,然后点击绿色区域 - 没有混合回调
完整的模块代码
import SwiftUI
struct TestGesturesPriority: View
var body: some View
VStack
Text("Hello, World!")
.padding()
.background(Color.yellow)
.gesture(TapGesture().onEnded
print(" -- child")
)
.frame(width: 400, height: 400)
.background(Color.green)
.gesture(TapGesture().onEnded
print(">> parent")
)
更新:List-Row
的变体
Yeees... List (Parent) - Row (Child) 案例看起来非常具有挑战性...请找到下面的方法,它看起来很奇怪,但经过测试和工作
struct TestGesturesPriority: View
let parentGesture = TapGesture().onEnded // just for convenience
print(">> parent")
@GestureState private var captured = false
var body: some View
List
Text("Hello, World!").padding()
.background(Color.yellow)
.allowsHitTesting(true)
.gesture(DragGesture(minimumDistance: 0) // mimic Tap
.updating($captured, body: (value, state, transaction) in
state = true // mark captured (will be reset automatically)
)
.onEnded value in
// like Tap, but can be ignored if delta
// is large or out of view
print(" -- child")
)
.gesture(parentGesture, including: captured ? .subviews : .gesture)
总结一下——其实我认为是另一个List缺陷
【讨论】:
也许在 List (Parent) > Row (Child) 里面有什么不同? @MichałZiobro,参见更新部分 让孩子取消从遍历到父母的手势是很疯狂的这困难 - 但你拯救了一天!【参考方案2】:在List
中有一种更简洁的方法来解决点击本地化问题,如下所示:
struct TestListGestures: View
var body: some View
List
Text("Hello, World!").padding()
.background(Color.yellow)
.gesture(LongPressGesture(minimumDuration: 0.001) // resolve response time
.onEnded value in
print(" -- child")
)
.gesture(LongPressGesture(minimumDuration: 0.001).onEnded( _ in
print(" -- parent")
), including: .gesture)
【讨论】:
以上是关于SwiftUI:取消父视图上的 TapGesture的主要内容,如果未能解决你的问题,请参考以下文章