iOS - forward all touches through a view

2019-01-04 08:52发布

I have a view overlayed on top of many other views. I am only using the overaly to detect some number of touches on the screen, but other than that I don't want the view to stop the behavior of other views underneath, which are scrollviews, etc. How can I forward all the touches through this overlay view? It is a subcalss of UIView.

9条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-01-04 09:18

Improved version of @fresidue answer. You can use this UIView subclass as transparent view passing touches outside its subview. Implementation in Objective-C:

@interface PassthroughView : UIView

@end

@implementation PassthroughView

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    for (UIView *view in self.subviews) {
        if (!view.hidden && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
            return YES;
        }
    }
    return NO;
}

@end

and in Swift:

class PassthroughView: UIView {
  override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    return subviews.contains(where: {
      !$0.isHidden && $0.point(inside: self.convert(point, to: $0), with: event)
    })
  }
}
查看更多
做自己的国王
3楼-- · 2019-01-04 09:18

Try something like this...

for (UIView *view in subviews)
  [view touchesBegan:touches withEvent:event];

The code above, in your touchesBegan method for example would pass the touches to all of the subviews of view.

查看更多
Root(大扎)
4楼-- · 2019-01-04 09:19

As suggested by @PixelCloudStv if you want to throw touched from one view to another but with some additional control over this process - subclass UIView

//header

@interface TouchView : UIView

@property (assign, nonatomic) CGRect activeRect;

@end

//implementation

#import "TouchView.h"

@implementation TouchView

#pragma mark - Ovverride

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL moveTouch = YES;
    if (CGRectContainsPoint(self.activeRect, point)) {
        moveTouch = NO;
    }
    return moveTouch;
}

@end

After in interfaceBuilder just set class of View to TouchView and set active rect with your rect. Also u can change and implement other logic.

查看更多
再贱就再见
5楼-- · 2019-01-04 09:21

This is an old thread, but it came up on a search, so I thought I'd add my 2c. I have a covering UIView with subviews, and only want to intercept the touches that hit one of the subviews, so I modified PixelCloudSt's answer to

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    for (UIView* subview in self.subviews ) {
        if ( [subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil ) {
            return YES;
        }
    }
    return NO;
}
查看更多
Rolldiameter
6楼-- · 2019-01-04 09:21

I had a similar issue with a UIStackView (but could be any other view). My configuration was the following: View controller with containerView and StackView

It's a classical case where I have a container that needed to be placed in the background, with buttons on the side. For layout purposes, I included the buttons in a UIStackView, but now the middle (empty) part of the stackView intercepts touches :-(

What I did is create a subclass of UIStackView with a property defining the subView that should be touchable. Now, any touch on the side buttons (included in the * viewsWithActiveTouch* array) will be given to the buttons, while any touch on the stackview anywhere else than these views won't be intercepted, and therefore passed to whatever is below the stack view.

/** Subclass of UIStackView that does not accept touches, except for specific subviews given in the viewsWithActiveTouch array */
class NoTouchStackView: UIStackView {

  var viewsWithActiveTouch: [UIView]?

  override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {

    if let activeViews = viewsWithActiveTouch {
        for view in activeViews {
           if CGRectContainsPoint(view.frame, point) {
                return view

           }
        }
     }
     return nil
   }
}
查看更多
Ridiculous、
7楼-- · 2019-01-04 09:27

Just an update, in Swift 4.0 and above this worked for me:

myWebView.isUserInteractionEnabled = false;
查看更多
登录 后发表回答