命中测试位于 SuperView 边界之外的 UIButton

Posted

技术标签:

【中文标题】命中测试位于 SuperView 边界之外的 UIButton【英文标题】:Hit Testing a UIButton located outside bounds of SuperView 【发布时间】:2015-10-22 01:45:51 【问题描述】:

我正在尝试将 touchUpInside 中的 UIButton 中的 ControlsView 动画化,这是所附图像中白色方块内的胡萝卜字符。当按下按钮时,一个委托方法被触发,controlsView 被激活。问题是因为UIButton 超出了controlsView 的范围,所以它没有接收到触摸信息。

我对此进行了很多思考,并阅读了一些潜在的候选解决方案。比如通过覆盖hitTest:withEvent:来检测超级视图上的触摸事件。但是,UIButton 实际上是CockPitView 的子视图,ControlsViewMainView 的子视图。 MainView 似乎是坐标UIButton 真正所在的矩形。所以我会在那里覆盖hitTest 并将触摸信息传递给CockPitView,然后我可以让我的Button 触发它的动作回调?

有没有人遇到过这个或类似的问题,并且对如何进行有任何建议?

【问题讨论】:

实际上,我的书中对此进行了讨论,并提供了一个简单解决方案的代码:apeth.com/iosBook/ch18.html#_hit_testing 【参考方案1】:

您应该在自定义视图CockPitView 中覆盖hitTest

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
   
    if (!self.clipsToBounds && !self.hidden && self.alpha > 0) 
        for (UIView *subview in self.subviews.reverseObjectEnumerator) 
            CGPoint subPoint = [subview convertPoint:point fromView:self];
            UIView *result = [subview hitTest:subPoint withEvent:event];
            if (result != nil) 
                return result;
            
        
    

    return nil;

CockPitView 必须是UIView 的子类

【讨论】:

【参考方案2】:

您可能想使用-pointInside:withEvent:。在您的button 的超级视图中,即ControlsView,重写如下方法:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

    // self.button is the button outside the bounds of your ControlsView
    if (CGRectContainsPoint(self.button.bounds, [self convertPoint:point toView:self.button])) 
        return YES;
    
    return [super pointInside:point withEvent:event];

通过这样做,您的ControlsView 声称您的按钮边界内的点应该被视为您的ControlsView 内的点。

【讨论】:

以上是关于命中测试位于 SuperView 边界之外的 UIButton的主要内容,如果未能解决你的问题,请参考以下文章

XCUIElement 存在,但不可命中

如果值在边界之外,则边界上的散点图绘制

如何禁止 CALayers 响应命中测试?

UICollectionViewCell 上的自定义命中测试

如何用户 XIB 使 SuperView 匹配 Subview 的框架? (Xcode 8)

当测试点位于多边形边缘时,多边形算法中的点返回真