How to fire UITapGestureRecognizer on a child view that is partially clipped by parent view?
cocoa-touch, uigesturerecognizer, uiview
Solution
This quote will answer your question as to why it behaves like that:
Touch events. The window object uses hit-testing and the responder chain to find the view to receive the touch event. In hit-testing, a window calls hitTest:withEvent: on the top-most view of the view hierarchy; this method proceeds by recursively calling pointInside:withEvent: on each view in the view hierarchy that returns YES, proceeding down the hierarchy until it finds the subview within whose bounds the touch took place. That view becomes the hit-test view. (source)
One workaround is to create your own `UITapInSubviewsView` with the following definition for `hitTest`:
(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
UIView *iSubView;
while ((iSubView = [reverseE nextObject])) {
UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
if(viewWasHit)
return viewWasHit;
}
return [super hitTest:point withEvent:event];
}
Then you use this class for your parent view.
(I found this code in a post from S.O. a few weeks ago, but I cannot seem to find it anymore; so just copied it from my project).
Problem
Setup: I have parent view A. It has a child view B. B is partially inside the bounds of A, but partially outside (A has clipsToBounds=false). I have attached UITapGestureRecognizer (UITGR) to B. Observed: UITGR fires OK when I tap on the portion of B that is within the bounds of A. UITGR does NOT fire when I tap on the portion of B that is outside the bounds of A. Expected/question: How do I make UITGR fire when I tap on the portion of B that is outside the bounds of A?