Reputation: 14834
I have a UIView called view1. view1 has a subview called subview. I added UITapGestureRecognizer
to subview as follow:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
[subview addGestureRecognizer:recognizer];
If I tapped an area overlapped between subview and view1 then the handleTap method got called. But if I tapped an area on the subview that was outside view1, then handleTap never got called. Is this behavior right? If not, any suggestion to what should I check for?
btw: The UIPanGestureRecognizer works fine. It does not exhibit the behavior mentioned above.
Upvotes: 7
Views: 3645
Reputation: 884
Probably the simplest way is to move subview at the top level of hierarchy, set constraints so that it is positioned correctly and put subview below view1 in storyboard list of objects (so that subview sits over view1). Of course, we loose some advantages of putting inside view1 (as automatic hiding when view1 is hidden…
Upvotes: 0
Reputation: 26385
That is the default behaviour of UIView
, the subview should be inside parent view bounds. If you want something different is better you create a custom subclass of the top view and override (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
Upvotes: 2
Reputation: 105
I've found the answers talking about overriding pointInside:withEvent: to be lacking detail on explanation or implementation. In the original question, when the user taps in the black, unlabeled area/view (we'll call it view2), the event framework will only trigger hitTest:withEvent: for the main window down through the view2 (and its immediate subviews), and will never hit it for view1 because the point tested for in pointInside:point is outside of the bounds of view1's frame. In order to get subview1 to register the gesture, you should override view2's implementation of hitTest:withEvent to include a check for subview's pointInside:point
//This presumes view2 has a reference to view1 (since they're nested in the example).
//In scenarios where you don't have access, you'd need to implement this
//in a higher level in the view hierachy
//In view2
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let ptRelativeToSubviewBounds = convert(point, to: view1.subview)
if view1.subview.point(inside:ptRelativeToSubviewBounds, with:event){
return view1.subview
}
else{
return super.hitTest(point, with: event)
}
Upvotes: 1
Reputation: 2206
You need to customize the parent view and change the way it handles touches. See this question for more details.
Upvotes: 1