iphone/ipad - parent UIView is blocking touches from getting to subviews - why?

10,309

Solution 1

Had to do with the frame of the parent view. If the frame doesn't enclose the subviews they won't receive touches.

Solution 2

UIView touches do not get passed to subviews if they lie outside of the superview's bounds as mentioned by the solution.

However if you want these subviews to respond to touch, override hitTest:withEvent: of the superview.

Documentation on Event Delivery

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.

  1. Create a subclass of UIView (or other UIView subclass).
  2. Override hitTest:withEvent.
  3. Use this UIView subclass as the superview, so subview can respond to touches.

Add method below in subclass:

(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];
}

Note: Reverse enumerator used since subviews are ordered from back to front and we want to test the front most view first.

Share:
10,309
sol
Author by

sol

Updated on June 18, 2022

Comments

  • sol
    sol almost 2 years

    I have a UIView which has a bunch of subviews. The subviews should be able to receive touch events, but for some reason the parent UIView takes the touch and does not pass it on. I have created it in a very standard way like I always create views:

    UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0,0,1024,768)];
        self.mainView = myView;
        [myView release];
    
        [self.view addSubview:self.mainView];
    

    Then I create subviews and add them as normal:

    [self.mainView addSubview:someOtherView];
    

    I know self.mainView is getting the touch events when I listen in the main UIWindow:

    VIEW: <UIView: 0x8d34aa0; frame = (0 0; 1024 768);
    

    But why in the world can I not get the subviews to receive touches? I don't understand why this happens sometimes. I am not changing any default properties of mainView.

  • sol
    sol over 13 years
    I don't have any touch handlers. The subviews just are not responding to touches. For example a GestureRecognizer on one of the subviews doesn't work.
  • MOK9
    MOK9 over 11 years
    also keep in mind to reference the 'bounds' of your parent view when positioning your subviews on screen. Your frame may or may not be the actual position on the screen.
  • Montana Burr
    Montana Burr over 8 years
    @sol: How do you know if that's the case?