使用hitTest:withEvent捕获其超级视图框架外的子视图的触摸: [英] Capturing touches on a subview outside the frame of its superview using hitTest:withEvent:

查看:127
本文介绍了使用hitTest:withEvent捕获其超级视图框架外的子视图的触摸:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题:我有一个超级视图 EditView 基本上占用了整个应用程序框架,并且子视图 MenuView 只占底部〜20%,然后 MenuView 包含自己的子视图 ButtonView 实际上位于 MenuView 的边界之外(类似这样: ButtonView.frame.origin.y = -100 )。

My problem: I have a superview EditView that takes up basically the entire application frame, and a subview MenuView which takes up only the bottom ~20%, and then MenuView contains its own subview ButtonView which actually resides outside of MenuView's bounds (something like this: ButtonView.frame.origin.y = -100).

(注意: EditView 有其他子视图不属于 MenuView 的视图层次结构,但可能会影响答案。)

(note: EditView has other subviews that are not part of MenuView's view hierarchy, but may affect the answer.)

你可能已经知道这个问题:当 ButtonView MenuView 的范围内(或者更具体地说,当我的触摸在 MenuView 之内时的界限), ButtonView 响应触摸事件。当我的触摸超出 MenuView 的界限(但仍然在 ButtonView 的界限内)时,没有触摸事件是收到 ButtonView

You probably already know the issue: when ButtonView is within the bounds of MenuView (or, more specifically, when my touches are within MenuView's bounds), ButtonView responds to touch events. When my touches are outside of MenuView's bounds (but still within ButtonView's bounds), no touch event is received by ButtonView.

示例:


  • (E)是 EditView ,所有观点的父母

  • (M) ) MenuView ,EditView的子视图

  • (B)是 ButtonView ,MenuView的子视图

  • (E) is EditView, the parent of all views
  • (M) is MenuView, a subview of EditView
  • (B) is ButtonView, a subview of MenuView

图表:

+------------------------------+
|E                             |
|                              |
|                              |
|                              |
|                              |
|+-----+                       |
||B    |                       |
|+-----+                       |
|+----------------------------+|
||M                           ||
||                            ||
|+----------------------------+|
+------------------------------+

因为(B)在(M)的框架外,所以(B)区域的抽头永远不会被发送到(M) - 实际上,(M) )在这种情况下永远不会分析触摸,触摸将被发送到层次结构中的下一个对象。

Because (B) is outside (M)'s frame, a tap in the (B) region will never be sent to (M) - in fact, (M) never analyzes the touch in this case, and the touch is sent to the next object in the hierarchy.

目标:我收集到了覆盖 hitTest:withEvent:可以解决这个问题,但我不知道究竟是怎么回事。在我的情况下,应该 hitTest:withEvent: EditView (我的'主'超级视图)中被覆盖?或者它应该在 MenuView 中被覆盖,是否没有接收到触摸的按钮的直接超级视图?或者我是否错误地考虑了这个问题?

Goal: I gather that overriding hitTest:withEvent: can solve this problem, but I don't understand exactly how. In my case, should hitTest:withEvent: be overridden in EditView (my 'master' superview)? Or should it be overridden in MenuView, the direct superview of the button that is not receiving touches? Or am I thinking about this incorrectly?

如果这需要冗长的解释,一个好的在线资源会有所帮助 - 除了Apple的UIView文档,它还没有说清楚我。

If this requires a lengthy explanation, a good online resource would be helpful - except Apple's UIView docs, which have not made it clear to me.

谢谢!

推荐答案

我修改了接受的答案代码更通用 - 它处理视图将子视图剪辑到其边界的情况,可能是隐藏的,更重要的是:如果子视图是复杂的视图层次结构,则会返回正确的子视图。

I have modified the accepted answer's code to be more generic - it handles the cases where the view does clip subviews to its bounds, may be hidden, and more importantly : if the subviews are complex view hierarchies, the correct subview will be returned.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    if (self.clipsToBounds) {
        return nil;
    }

    if (self.hidden) {
        return nil;
    }

    if (self.alpha == 0) {
        return nil;
    }

    for (UIView *subview in self.subviews.reverseObjectEnumerator) {
        CGPoint subPoint = [subview convertPoint:point fromView:self];
        UIView *result = [subview hitTest:subPoint withEvent:event];

        if (result) {
            return result;
        }
    }

    return nil;
}

SWIFT 3

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

    if clipsToBounds || isHidden || alpha == 0 {
        return nil
    }

    for subview in subviews.reversed() {
        let subPoint = subview.convert(point, from: self)
        if let result = subview.hitTest(subPoint, with: event) {
            return result
        }
    }

    return nil
}

我希望这有助于任何人尝试将此解决方案用于更复杂的用例。

I hope this helps anyone trying to use this solution for more complex use cases.

这篇关于使用hitTest:withEvent捕获其超级视图框架外的子视图的触摸:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆