关于这个问题,其实网上有很多技术博客给出了很好的方案,但是仍然有个别博客将有严重错误的结论挂在网上(例如),本文就该问题进行了严格的论证,希望能够帮到有需要的人。
错误结论:每次递归去调用hitTest:(CGPoint)point withEvent:(UIEvent *)event之前,都会调用pointInside:withEvent:来确定该触摸点是否在该View内。
正确结论:先调用hitTest:(CGPoint)point withEvent:(UIEvent *)event,而后调用pointInside:withEvent:。
那么点击超出父视图但在子视图的区域时,要想响应事件到底怎么处理最合理?
正确答案:
重写父视图方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (self.userInteractionEnabled == NO && self.alpha <= 0.01 && self.hidden == YES) {
return nil;
}
if (view == nil) {
for (UIView * subview in self.subviews.reverseObjectEnumerator) {
CGPoint converP = [subview convertPoint:point fromView:self];
UIView *suitableView = [subview hitTest:converP withEvent:event];
if (suitableView) {
return suitableView;
} else {
return view;
}
}
}
return view;
}
相关知识:Hit-test view的应用
扩大UIButton的点击区域
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
return CGRectContainsPoint(HitTestingBounds(self.bounds, self.minimumHitTestWidth, self.minimumHitTestHeight), point);
}
CGRect HitTestingBounds(CGRect bounds, CGFloat minimumHitTestWidth, CGFloat minimumHitTestHeight) {
CGRect hitTestingBounds = bounds;
if (minimumHitTestWidth > bounds.size.width) {
hitTestingBounds.size.width = minimumHitTestWidth;
hitTestingBounds.origin.x -= (hitTestingBounds.size.width - bounds.size.width)/2;
}
if (minimumHitTestHeight > bounds.size.height) {
hitTestingBounds.size.height = minimumHitTestHeight;
hitTestingBounds.origin.y -= (hitTestingBounds.size.height - bounds.size.height)/2;
}
return hitTestingBounds;
}