5

设置:我有父视图 A。它有一个子视图 B。B 部分位于 A 的边界内,但部分位于 A 的边界之外(A 的 clipsToBounds=false)。我已将 UITapGestureRecognizer (UITGR) 附加到 B.

观察到:当我点击 A 范围内的 B 部分时,UITGR 触发 OK。当我点击 A 范围之外的 B 部分时,UITGR 不会触发。

预期/问题:当我点击 A 边界之外的 B 部分时,如何使 UITGR 触发?

4

3 回答 3

7

这句话将回答你关于它为什么会这样的问题:

触摸事件。窗口对象使用命中测试和响应者链来找到接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用 hitTest:withEvent:;此方法通过在视图层次结构中返回 YES 的每个视图上递归调用 pointInside:withEvent: 来继续,沿着层次结构向下进行,直到找到发生触摸的子视图。该视图成为命中测试视图。(来源

UITapInSubviewsView一种解决方法是使用以下定义创建您自己的hitTest

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
    UIView *iSubView;
    while ((iSubView = [reverseE nextObject])) {

        UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
        if(viewWasHit)
           return viewWasHit;
     }
     return [super hitTest:point withEvent:event];
}

然后你将这个类用于你的父视图。

(几周前我在 SO 的一篇帖子中找到了这段代码,但我似乎再也找不到它了;所以只是从我的项目中复制了它)。

于 2012-05-17T08:31:08.547 回答
1

更新@sergioSwift 4.2的回答:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let reversedSubviews = subviews.reversed()
    let hitSubview = reversedSubviews
        .first(where: { $0.hitTest(convert(point, to: $0), with: event) != nil })
    if hitSubview != nil {
        return hitSubview
    }

    return super.hitTest(point, with: event)
}
于 2019-02-15T21:06:58.220 回答
0

您必须为视图 A 编写自己的 hittest 函数。

还要看这个问题:UITapGestureRecognizer not trigger in deep view hiearchy

于 2012-05-16T14:38:53.327 回答