iOS – 通过视图转发所有触摸

我有一个覆盖在许多其他意见的顶部的观点。 我只是用来检测屏幕上的一些触摸,但除此之外,我不希望视图停止下面的其他视图的行为,这是滚动视图,等等。我怎样才能转发所有的触摸这个覆盖视图? 这是UIView的一个subcalss。

为了将覆盖视图的触摸传递给下面的视图,请在UIView中实现以下方法:

Objective-C的:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { NSLog(@"Passing all touches to the next view (if any), in the view stack."); return NO; } 

迅速:

 override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { print("Passing all touches to the next view (if any), in the view stack.") return false } 
 myWebView.userInteractionEnabled = NO; 

是我所需要的!

这是一个古老的线索,但它出现在search,所以我想我会添加我的2C。 我有覆盖子视图的UIView,只想拦截其中一个子视图的触摸,所以我修改了PixelCloudSt的答案

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

改进的@fresidue答案。 你可以使用这个UIView子类作为在其子视图之外传递触摸的透明视图。 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 

Swift中:

 class PassthroughView: UIView { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return subviews.contains(where: { !$0.isHidden && $0.point(inside: point, with: event) }) } } 

如果你想转发触摸的视图不会碰巧是一个子视图/超视图,你可以在你的UIView子类中设置一个自定义属性,如下所示:

 @interface SomeViewSubclass : UIView { id forwardableTouchee; } @property (retain) id forwardableTouchee; 

确保在你的.m文件中进行合成:

 @synthesize forwardableTouchee; 

然后在你的任何一个UIResponder方法中包含以下内容:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.forwardableTouchee touchesBegan:touches withEvent:event]; } 

无论你在哪里实例化你的UIView,都将forwardableTouchee属性设置为你希望事件被转发到的任何视图:

  SomeViewSubclass *view = [[[SomeViewSubclass alloc] initWithFrame:someRect] autorelease]; view.forwardableTouchee = someOtherView; 

我有一个类似的问题与UIStackView(但可以是任何其他的看法)。 我的configuration如下: 使用containerView和StackView查看控制器

这是一个经典的案例,我有一个需要放在背景中的容器,旁边有button。 为了布局的目的,我在UIStackView中包含了这些button,但是现在stackView的中间(空)部分拦截了触摸:-(

我所做的是创build一个UIStackView的子类与一个属性定义的子视图,应该是可触摸的。 现在,button(包含在* viewsWithActiveTouch *数组中)的任何触摸都将被赋予button,而在任何其他位置的视图上的任何触摸都不会被截取,因此将被传递给堆栈下的任何东西视图。

 /** 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 } } 

尝试这样的事情…

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

上面的代码,例如touchesBegan方法会将触摸传递给所有的视图子视图。

正如@PixelCloudStv所build议的,如果你想从一个视图触到另一个视图,但是对这个过程有一些额外的控制 – 子类UIView

//头

 @interface TouchView : UIView @property (assign, nonatomic) CGRect activeRect; @end 

//执行

 #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 

在interfaceBuilder中,只需将View的类设置为TouchView,并用你的矩形设置活动矩形。 你也可以改变和实现其他的逻辑。