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如下:
这是一个经典的案例,我有一个需要放在背景中的容器,旁边有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,并用你的矩形设置活动矩形。 你也可以改变和实现其他的逻辑。