简体   繁体   中英

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

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.

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

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.

Does you touch handlers call the superclass handlers?

eg in your touchesBegan, calling:

[super touchesBegan:touches withEvent:event];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM