Passing through touches to UIViews underneath

前端 未结 5 1352
庸人自扰
庸人自扰 2020-12-01 03:17

I have a UIView with 4 buttons on it and another UIView on top of the buttons view. The top most view contains a UIImageView with a <

相关标签:
5条回答
  • 2020-12-01 03:49

    I have a another solution. I have two views, let's call them CustomSubView that were overlapping and they should both receive the touches. So I have a view controller and a custom UIView class, lets call it ViewControllerView that I set in interface builder, then I added the two views that should receive the touches to that view.

    So I intercepted the touches in ViewControllerView by overwriting hitTest:

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        return self;
    }
    

    Then I overwrote in ViewControllerView:

    - (void)touchesBegan:(NSSet *)touches
               withEvent:(UIEvent *)event
    {
        [super touchesBegan:touches withEvent:event];
        for (UIView *subview in [self.subviews reverseObjectEnumerator])
        {
            if ([subview isKindOfClass:[CustomSubView class]])
            {
                [subview touchesBegan:touches withEvent:event];
            }
        }
    }
    

    Do the exact same with touchesMoved touchesEnded and touchesCancelled.

    0 讨论(0)
  • 2020-12-01 03:49

    @Magic Bullet Dave's solution but in Swift

    Swift 3

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        var pointInside = false
        if commentTextField.frame.contains(point) {
            pointInside = true
        } else {
            commentTextField.resignFirstResponder()
        }
        return pointInside
    }
    

    I use it in my CameraOverlayView for ImagePickerViewController.cameraOverlay to give user ability to comment while taking new photo

    0 讨论(0)
  • 2020-12-01 03:59

    Select your View in Storyboard or XIB and...


    enter image description here


    Or in Swift

    view.isUserInteractionEnabled = false
    
    0 讨论(0)
  • 2020-12-01 04:09

    Look into the UIGestureRecognizerDelegate Protocol. Specifically, gestureRecognizer:shouldReceiveTouch:

    You'll want to make each UIGestureRecognizer a property of your UIViewController,

    // .h
    @property (nonatomic, strong) UITapGestureRecognizer *lowerTap;
    
    // .m
    @synthesize lowerTap;
    
    // When you are adding the gesture recognizer to the image view
    self.lowerTap = tapGestureRecognizer
    

    Make sure you make your UIViewController a delegate,

    [self.lowerTap setDelegate: self];
    

    Then, you'd have something like this,

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if (expanded && gestureRecognizer == self.lowerTap) {    
            return NO;
        }
        else {
            return YES;
        }
    }
    

    Of course, this isn't exact code. But this is the general pattern you'd want to follow.

    0 讨论(0)
  • 2020-12-01 04:11

    The UIGestureRecognizer is a red herring I think. In the end to solve this I overrode the pointInside:withEvent: method of my UIView:

    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
        BOOL pointInside = NO;
    
        if (CGRectContainsPoint(imageView.frame, point) || expanded) pointInside = YES;
    
        return pointInside;
    }
    

    This causes the view to trap all touches if you touch either the imageView or if its expanded flag is set. If it is not expanded then only trap the touches if they are on the imageView.

    By returning NO, the top level VC's View queries the rest of its view hierarchy looking for a hit.

    0 讨论(0)
提交回复
热议问题