My problem:我有一个superview EditView,它基本上占据了整个应用程序框架,还有一个子视图MenuView,它只占底部的20%,然后MenuView包含它自己的子视图ButtonView,它实际上位于MenuView的边界之外(类似于:ButtonView.frame.origin.y = -100).

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

你可能已经知道这个问题了:当ButtonViewMenuView的范围内(或者更具体地说,当我的touch 在MenuView的范围内时),ButtonView会响应touch 事件.当我的touch 超出MenuView的界限(但仍在ButtonView的界限内)时,ButtonView不会收到任何touch 事件.

Example:

  • (E) 是EditView,是所有视图的父视图
  • (M)为MenuView,为EditView的子视图
  • (B)为ButtonView,为MenuView的子视图

Diagram:

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

因为(B)在(M)的框之外,所以(B)区域中的轻击将永远不会被发送到(M)-事实上,(M)在这种情况下从不分析touch ,并且touch 被发送到层次中的下一个对象.

Goal:我想凌驾于hitTest:withEvent:之上可以解决这个问题,但我不知props 体是怎么解决的.在我的例子中,应该在EditView(我的"主"SuperView)中重写hitTest:withEvent:吗?或者它应该在MenuView中被覆盖,MenuView是不接受touch 的按钮的直接SuperView?还是我想错了?

如果这需要一个冗长的解释,一个好的在线资源会很有帮助——除了苹果的UIView文档,它没有向我明确说明.

谢谢

推荐答案

我已经修改了接受答案的代码,使其更加通用——它处理视图将子视图剪裁到其边界、可能被隐藏的情况,更重要的是:如果子视图是复杂的视图层次 struct ,则将返回正确的子视图.

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

我希望这能帮助任何试图将此解决方案用于更复杂用例的人.

Ios相关问答推荐

Flutter应用程序无法使用IOS/Swift的蓝牙核心库发现某些外围设备

SwiftUI中ForEach和@ State数组的可能并发问题

preferredCompactColumn作为NavigationSplitViewColumn.sidebar传递,但仍能在iOS上看到详细信息页面

使用AVCaptureEventInteraction捕获音量按键快门

Swift-如何通过Case Let访问模型变量

iOS上从谷歌云存储API不断收到网络连接已丢失的错误信息

更改图标会导致 SwiftUI 动画出现故障?

将值传递给导航链接视图中的文本框

来自 c++ 的runtime_error未在 iOS 中捕获

为什么我不能让 passthrough 科目为 combine 工作?

在 UICollectionView 上动态设置布局导致莫名其妙的 contentOffset 变化

如何阻止图像在 UIImageView 中拉伸?

将图像保存到 Documents 目录并检索邮箱附件

正确的领域使用模式/最佳实践?

关闭通过模态 segue 显示的视图

如何关闭 iOS 键盘?

有什么方法可以加粗 NSString 的一部分?

iPhone:什么是 WWDR 中级证书?

打开 XIB 文件后 Xcode 6.3 冻结/挂起

UIGestureRecognizer 阻止子视图处理touch 事件