【问题标题】:How to fire UITapGestureRecognizer on a child view that is partially clipped by parent view?如何在被父视图部分裁剪的子视图上触发 UITapGestureRecognizer?
【发布时间】:2012-05-07 04:07:22
【问题描述】:

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

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

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

【问题讨论】:

    标签: cocoa-touch uiview uigesturerecognizer


    【解决方案1】:

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

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

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

    (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];
    }
    

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

    (几周前我在 S.O. 的一篇文章中找到了这段代码,但我似乎再也找不到了;所以从我的项目中复制了它)。

    【讨论】:

      【解决方案2】:

      @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)
      }
      

      【讨论】:

        【解决方案3】:

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

        也看这个问题:UITapGestureRecognizer not triggered in deep view hiearchy

        【讨论】:

        • 你能否扩展一下关于这个原因的答案——是因为默认的命中测试忽略了父视图边界之外的触摸吗?而且我需要测试自己的触摸是否在子范围内?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-29
        相关资源
        最近更新 更多