【问题标题】:Stop propagation of touch event to views behind in Swift停止将触摸事件传播到 Swift 后面的视图
【发布时间】:2021-03-07 21:20:25
【问题描述】:

我里面有一个滚动视图和一个子视图。如果用户在该子视图中进行了某种触摸,我想阻止滚动视图移动,以便让用户在子视图中做他们的事情而不会被滚动视图移动所困扰。如果没有检测到某个触摸,则滚动视图应该正常移动。

我使用原始触摸事件touchesBegantouchesMoved 拦截这些手势。我不使用gestureRecognizers,因为我想识别的手势非常具体,而且我觉得不使用抽象层来识别它们更舒服。

我知道在看到很多关于 SO 的答案后,如果我检测到手势,我可以只保留滚动视图的引用并停止其移动。我正在寻找更稳定的解决方案。如果我检测到手势,我想停止事件的传播(到后面的任何视图),而不必保留任何这些视图的引用。

据我了解,iOS 中的视图是 UIResponder 的子类。当 UIKit 检测到屏幕上的触摸时,它会将事件提供给第一响应者,该响应者通常是最顶层的子视图。我的问题是:在touchesBegan 如何告诉 UIKit:“不要将事件发送到响应者链中的任何其他后续视图”。如果我可以看到滚动视图在后面移动,那么 UIKit 一定已经将事件转发给它(尽管我没有在 touchesBegan 中调用 super

例如在 Android 中,View 类的 onTouchEvent 函数返回一个布尔值。 false 告诉 android 继续传播事件, true 告诉停止传播。我在 iOS 中寻找同样的机制:

@Override
public boolean onTouchEvent(MotionEvent e)
{
    return true ; // stops propagation 
}

在 Javascript (jQuery) 中,有完全相同的机制:

$('#myview').bind('click', function(e) {
    e.stopPropagation() 
})

如何在 Swift 中做到这一点?

【问题讨论】:

  • this设置为false怎么样?
  • 这是 UIScrollView 的一个属性。我一直在寻找一个比持有我想要关闭的视图的引用更稳定的解决方案。明确:我希望 uiscrollview 甚至不知道触摸事件(并且在检测到触摸后不取消移动)
  • 我还没有尝试过,但是如何覆盖自定义视图的next 属性,它应该返回下一个响应者,以在检测到手势时返回nil
  • 在我的子视图中尝试了override var next:UIResponder? { get { return nil }},但滚动视图仍然落后:/
  • 找到了解决方案(发布在我的答案中):)

标签: swift events uikit touch uiresponder


【解决方案1】:

找到了解决办法。这很难理解,所以如果有人遇到同样的问题,我会尽量简化:

正如另一个 SO 答案中所述,“原始触摸系统”(touchesBegentouchesMoved ..)和“手势识别系统”是互斥的,它们实际上都处于“原始”视图级别,并且有独立的。

这意味着当您拥有一个视图并触摸它时,您的触摸有可能由手势识别系统而不是原始触摸系统处理。 override var next:UIResponder? { get { return nil }} 覆盖 next UIResponder 属性仅强制 UIKit 不转发事件在原始触摸系统中,仍然触发后面视图的手势识别,因为它是一个完全独立的系统。

就我而言,我尝试了override var next:UIResponder? { get { return nil }}:后面的视图touchesBegan 保持安静,但我仍然可以识别那里的手势。

因此,UIScrollView 似乎使用了gestureRecognizer 来处理用户触摸。解决方案是从最顶部的视图中关闭手势识别系统,这样手势就不会被转发:这可以使用:

override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 
{
    return !yourConditionToShutDownGR
}

我很困惑,因为 Android 的手势“检测器”系统建立在原始触摸系统之上。当您在public boolean onTouchEvent(MotionEvent event) 中捕捉到触摸事件时,您可以将其作为手势检测器的参数传递,如果它找到手势则返回。这与 iOS 中的手势识别系统建立在原始触摸系统之外的方法不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2017-04-28
    相关资源
    最近更新 更多