I thought when a view is touched or tapped on, its handler get called first, and then its superview's handler is called (propagate upward).
But is it true that if the superview's userInteractionEnabled
is set to NO, then all subviews and offspring is also disabled for user interaction? What if we want to disable for just the main view but don't want to disable for the subviews?
You cant do that,
Instead you would change the arrangment of your views like following:
Main View-> subViews
To
Container View -> Main View that you want to set as inactive
-> other views that you want to still active
So your current main view and you current subviews will become siblings, children of a new container view
If this may be helpful, I found this in Programming iOS 5 by Matt Neuburg, p. 467:
userInteractionEnabled
If set to NO, this view (along with its subviews) is excluded from
receiving touches. Touches on this view or one of its subviews "fall
through" to a view behind it.
Further more, Apple's Event Handling Guide for iOS says:
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.
and Programming iOS 5 by Matt Neuburg, p.485 mentioned that if a view is marked userInteractionEnabled
as NO
, or hidden
as YES
, or opacity is close to 0, then the view and its subview will not be traversed by HitTest
(and therefore not considered for any touch).
You can override hitTest(_:withEvent:)
to ignore the view itself, but still deliver touches to its subviews.
class ContainerStackView : UIStackView {
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
let result = super.hitTest(point, withEvent: event)
if result == self { return nil }
return result
}
}
First Method
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view.superview isKindOfClass:[SuperViewParent class]]) return FALSE;
return TRUE;
}
Second Method
UITapGestureRecognizer *r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(agentPickerTapped:)];
r.cancelsTouchesInView = NO;
[agentPicker addGestureRecognizer:r];