超越界面的互动

当UIButton的框架位于父框架之外时,UIButton(或其他任何控件)是否可以接收触摸事件? 因为当我尝试这个时,我的UIButton似乎不能接收任何事件。 我如何解决这个问题?

是。 你可以重写hitTest:withEvent:方法来返回比该视图包含的点集更大的视图。 请参阅UIView类参考 。

编辑:例如:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGFloat radius = 100.0; CGRect frame = CGRectMake(-radius, -radius, self.frame.size.width + radius, self.frame.size.height + radius); if (CGRectContainsPoint(frame, point)) { return self; } return nil; } 

编辑2 🙁澄清之后:)为了确保button被视为在父界限内,您需要覆盖pointInside:withEvent:在父项中以包含button的框架。

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if (CGRectContainsPoint(self.view.bounds, point) || CGRectContainsPoint(button.view.frame, point)) { return YES; } return NO; } 

注意那里的重写pointInside的代码不太正确。 正如Summon在下面解释的那样,这样做:

 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if ( CGRectContainsPoint(self.oversizeButton.frame, point) ) return YES; return [super pointInside:point withEvent:event]; } 

请注意,你很可能用self.oversizeButton作为这个UIView子类中的一个IBOutlet。 那么你可以拖动相应的“特大号”button。 (或者,如果由于某种原因,你在项目中做了很多事情,你会有一个特殊的UIButton子类,并且你可以查看这些类的子视图列表。)希望它有帮助。

@jnic,我正在iOS SDK 5.0上工作,为了让你的代码正常工作,我必须这样做:

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if (CGRectContainsPoint(button.frame, point)) { return YES; } return [super pointInside:point withEvent:event]; } 

在我的情况下容器视图是一个UIButton和所有的子元素也UIButtons可以移动到父UIButton的界限之外。

最好

在父视图中,您可以覆盖命中testing方法:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGPoint translatedPoint = [_myButton convertPoint:point fromView:self]; if (CGRectContainsPoint(_myButton.bounds, translatedPoint)) { return [_myButton hitTest:translatedPoint withEvent:event]; } return [super hitTest:point withEvent:event]; } 

在这种情况下,如果该点落在button的范围内,则在那里转接呼叫; 如果不是,则恢复到原始实施。

迅速:

其中,targetView是您希望接收事件的视图(可能完全或部分位于其父视图的框架之外)。

 override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { let pointForTargetView: CGPoint = targetView.convertPoint(point, fromView: self) if CGRectContainsPoint(targetView.bounds, pointForTargetView) { return closeButton } return super.hitTest(point, withEvent: event) } 

在我的情况下,我有一个包含UIButtonUICollectionViewCell子类。 我禁用了单元格上的clipsToBounds ,并且button在单元格边界之外是可见的。 但是,button没有收到触摸事件。 我能够通过使用杰克的答案检测button上的触摸事件: https : //stackoverflow.com/a/30431157/3344977

这是一个Swift版本:

 override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { let translatedPoint = button.convertPoint(point, fromView: self) if (CGRectContainsPoint(button.bounds, translatedPoint)) { print("Your button was pressed") return button.hitTest(translatedPoint, withEvent: event) } return super.hitTest(point, withEvent: event) } 

对我来说(和其他人一样),答案不是重写hitTest方法,而是重写pointInside方法。 我只能在两个地方做这个。

Superview这是这样的观点,如果它把clipsToBounds设置为true,就会使整个问题消失。 所以这里是我在Swift 3中简单的UIView

 class PromiscuousView : UIView { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return true } } 

子视图你的里程可能会有所不同,但在我的情况下,我也不得不覆盖subview的pointInside方法已经决定触摸超出界限。 我在Objective-C中,所以:

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { WEPopoverController *controller = (id) self.delegate; if (self.takeHitsOutside) { return YES; } else { return [super pointInside:point withEvent:event]; } } 

这个答案 (和其他一些关于同一个问题的答案 )可以帮助理清你的理解。