Detect if certain UIView was touched amongst other

2019-01-08 17:02发布

问题:

I have 3 UIViews, layered on top of one large uiview. I want to know if the user touches the top one and not care about the other ones. I will have a couple of buttons in the second UIView and a UITable in the 3rd UIView.

Problem is I turn userInteractionEngabled on on the first view and that works, but all the other views respond in the same way even if I turn it off. If I disable userInteractionEnabled on self.view none of them respond. I also can't detect which view was touched in the touchesBegan delegate method.

My code:

UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
aView = userInteractionEnabled = YES;
[self.view addSubview:aView];

UIView *bView = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 320, 50)];
bView.userInteractionEnabled = NO;
[self.view addSubview:bView];

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//This gets called for a touch anywhere
}

回答1:

In order to check whether certain view inside another view was touched you can use hitTest.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

In your custom implementation of touchesBegan check every touch in touches set. The point for hitTest method can be obtained using

- (CGPoint)locationInView:(UIView *)view;

method, where the view is your superView (the one that contains other views).

EDIT: Here's a fast custom implementation:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    CGPoint locationPoint = [[touches anyObject] locationInView:self];
    UIView* viewYouWishToObtain = [self hitTest:locationPoint withEvent:event];
}

I hope this was helpful, Paul



回答2:

In my case the UIView I wanted to find was not returned by the hitTest. But the following code worked better:

    CGPoint locationPoint = [[touches anyObject] locationInView:self.view];
    CGPoint viewPoint = [myImage convertPoint:locationPoint fromView:self.view];
    if ([myImage pointInside:viewPoint withEvent:event]) {
       do something
    }


回答3:

This can also be done the following way.

First find the location of the touch in the view you care about:

CGPoint location = [touches.anyObject locationInView:viewYouCareAbout];

Then see if the point is within the bounds of the view:

BOOL withinBounds = CGRectContainsPoint(viewYouCareAbout.bounds, location);

Then if it's within bounds, perform your action.

This can be done with one statement, which for example, can be used directly within an if statement:

CGRectContainsPoint(viewYouCareAbout.bounds, [touches.anyObject locationInView:viewYouCareAbout])


回答4:

swift code:

 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if let touch = touches.first {
            if touch.view == self.view {
                self.hideInView()
            } else {
                return
            }

        }
    }


回答5:

In touchesBegan check that the touched view is the one you want, solved the problem for me when I tried to identified if the user touched a specific ImageView.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    if ([touch view] ==  imageView ) {
        ... your code to handle the touch
    }
    ...

If you adjust the content for the view diamensions make sure to change the view size accordingly otherwise it will recognize touch event even in area where there in so content in the view. In my case when I tried to keep the image proportion with UIViewContentModeScaleAspectFit although the image was adjusted as required in the "white spaces" areas touch event were catched as well.



回答6:

My swift version to check that touch took place in infoView:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, infoView.bounds.contains(touch.location(in: infoView))  else { return }
    print("touchesBegan") // Replace by your own code
} // touchesBegan


回答7:

This worked for me:

func respondToGesture(gesture: UIGestureRecognizer) {
    let containsPoint = CGRectContainsPoint(targetView.bounds, gesture.locationInView(targetView))
}