如何忽略触摸事件并将它们传递给另一个子视图的UIControl对象?

Chr*_*s C 64 cocoa-touch uikit uiresponder ios

我有一个自定义的UIViewController,其UIView占据了屏幕的一角,但大部分都是透明的,除了它的部分有一些按钮和东西.由于该视图上对象的布局,视图的框架可以覆盖其下方的一些按钮.如果他们没有触及任何重要的东西,我希望能够忽略该视图上的任何触摸,但我似乎只能传递实际的触摸事件(touchesEnded/nextResponder的东西).如果我有一个UIButton或类似的东西没有使用touchesEnded,我如何将触摸事件传递给它?

我不能手动找出要调用的按钮选择器,因为这个自定义ViewController可用于许多不同的视图.我基本上需要一种方法来调用它:

[self.nextResponder touchesEnded:touches withEvent:event];

在UIControl类型上也是如此.

Stu*_*art 131

可能最好的方法是hitTest:withEvent:在视图中覆盖您想要忽略的触摸.根据视图层次结构的复杂程度,有几种简单的方法可以做到这一点.

如果您对视图下方的视图有引用,则忽略:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];

    // If the hitView is THIS view, return the view that you want to receive the touch instead:
    if (hitView == self) {
        return otherView;
    }
    // Else return the hitView (as it could be one of this view's buttons):
    return hitView;
}
Run Code Online (Sandbox Code Playgroud)

如果您没有对视图的引用:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];

    // If the hitView is THIS view, return nil and allow hitTest:withEvent: to
    // continue traversing the hierarchy to find the underlying view.
    if (hitView == self) {
        return nil;
    }
    // Else return the hitView (as it could be one of this view's buttons):
    return hitView;
}
Run Code Online (Sandbox Code Playgroud)

我建议第一种方法是最强大的(如果可以获得对底层视图的引用).

  • @chris:当然,只是将它子类化并抛出重写方法,如上所示.这意味着你将有一个额外的`.h`和`.m`文件,其中包含非常少的代码,但它可以完成这项工作.此外,直通视图是您的工具包中有用的子类.如果视图控制器在`nib`中创建视图,只需进入IB文件并将视图的类更改为身份检查器中的新子类.如果以编程方式创建,则在`loadView`中创建并分配视图子类(请参阅编辑). (4认同)

小智 13

您还可以禁用用户交互,以便忽略触摸事件并将其传递给父级.

在Swift中:

yourView.isUserInteractionEnabled = false
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是不对的。如果 isUserInteractionEnabled 为 true,则事件将被忽略并(根据 Apple 文档)“从事件队列中删除”。即它们不会按照OP想要的那样传递到下一个视图。 (3认同)

Kev*_*vin 11

快速回答:

您可以创建一个UIView子类IgnoreTouchView.在故事板中,将其设置在要通过触摸的VC视图上:

class IgnoreTouchView : UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, with: event)
        if hitView == self {
            return nil
        }
        return hitView
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,对于相关的UIView,您必须将UserInteractionEnabled设置为true!


Eri*_*icS 7

我还没有找到一种在对象之间传递UITouch事件的好方法.通常更好的方法是实现hitTest并返回nil,如果该点不在您要处理它的视图中:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Run Code Online (Sandbox Code Playgroud)