UIScrollView如何从其子视图中夺取触摸事件?

6
我希望能够创建自己的UIView容器子类,使其在子视图之前首先响应触摸事件。这很棘手,因为通常情况下,子视图会比父视图优先接收触摸事件(通过touchesBegan:等)。UIScrollView是如何颠倒这种现象的?
明确一点,我不是在询问UIScrollView的行为。我理解它的功能以及正常使用方式。我想了解如何干净地实现自己版本的此类行为,不是因为我想要这样做,而是因为我正在尝试构建可重用的容器视图,以充分利用类似的行为。
3个回答

13
你可以在你的UIView子类中实现hitTest:withEvent:方法。
该方法被调用以检查哪个子视图必须接收触摸事件,因此您可以在事件发生之前执行一些操作。您还可以更改必须接收事件的子视图。

太棒了。令人难以置信的棒。 - Tyler
但是,该方法的实现是什么?如果它是一个简单的触摸,UIScrollView 将使其子视图成为响应者。但如果它是一个滚动事件,UIScrollView 将成为响应者并处理滚动事件。如何将这个逻辑实现到其中? - Edward Anthony
1
@EdwardAnthony,坦白地说,7年后我会说将UIGestureRecognizers添加到您的自定义视图可能是正确的方法(您可以检查标准UIScrollView默认附加了几个手势识别器)。 - Vladimir

4

[编辑: 好的,我有些误读了问题,实际上与问题无关。如果有人感兴趣,我会留在这里,但它与实际问题无关 --TechZen]

滚动视图需要同时水平和垂直移动,因此必须对所有触摸进行采样以查看它们是否是滚动触摸。

例如,在滚动视图中有一个水平滚动的滑块。用户触摸滑块,那么这个触摸是用于滑动滑块还是水平滚动的开始?哪个应该优先处理?

尽管在程序上,响应链从最底部的视图(最上面的可视化视图)向上移动到找到处理它的对象,但在幕后,触摸位置的处理是从最上面的视图(即应用程序窗口)向下进行的。大多数视图只是将此信息转发给子视图,然后激活并发送事件到响应链以进行处理。由于滚动整个视图是一种特殊事件,它实际上不属于普通的响应链,因此滚动视图拦截触摸位置的下传,以确定是否需要滚动,然后再将触摸位置传递给子视图。


2
这里有一个非常简单但有效的方法。
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyBoard:)];
gestureRecognizer.delegate = self;
[scrollView addGestureRecognizer:gestureRecognizer];

-(void) hideKeyBoard:(id) sender
{
   // Do whatever such as hiding the keyboard
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接