如何禁用触摸input到除最顶层视图之外的所有视图?

我有一个观点与多个子视图。 当用户点击一个子视图时,子视图的大小会扩大到覆盖大部分屏幕,但其他一些子视图的底部仍然可见。

当其中一个子视图像这样“展开”时,我希望我的应用忽略其他子视图的触摸。 有一个简单的方法来实现这个? 我可以编写代码来处理这个问题,但我希望有一个更简单的内置方法。

希望这个帮助…

[[yourSuperView subviews] makeObjectsPerformSelector:@selector(setUserInteractionEnabled:) withObject:[NSNumber numberWithBool:FALSE]]; 

这将禁用视图的直接子视图的userInteraction ..然后给userInteraction到你想要的唯一视图

 yourTouchableView.setUserInteraction = TRUE; 

编辑:

看来在iOS中禁用父视图的userInteraction不会禁用其childs上的userInteraction .. 所以上面的代码(我的意思是与 makeObjectsPerformSelector: 只会禁用父母的直接子视图的userInteraction ..

查看用户madewulf的答案recursion获得所有的子视图,并禁用所有的用户交互。 或者如果你需要在项目中的许多地方禁用这个视图的userInteraction,你可以分类UIView添加该function..这样的事情会做..

 @interface UIView (UserInteractionFeatures) -(void)setRecursiveUserInteraction:(BOOL)value; @end @implementation UIView(UserInteractionFeatures) -(void)setRecursiveUserInteraction:(BOOL)value{ self.userInteractionEnabled = value; for (UIView *view in [self subviews]) { [view setRecursiveUserInteraction:value]; } } @end 

现在你可以打电话了

 [yourSuperView setRecursiveUserInteraction:NO]; 

另外,用户@ lxt的build议是在所有视图的顶部添加一个不可见视图是另一种方法。

有几种方法可以做到这一点。 你可以遍历所有其他的子视图,并设置userInteractionEnabled = NO ,但是如果你有很多其他的视图(毕竟你不得不随后将它们全部重新渲染),这是不太理想的。

我这样做的方式是创build一个不可见的UIView,它是整个屏幕的大小,阻止所有触及到其他视图的触摸。 有时候,这是字面上看不见的,有些时候我可能会把它设置为黑色,而且alpha值为0.3左右。

当你展开你的insertSubview: belowSubview:视图来填充屏幕时,你可以在它后面添加这个“阻塞”UIView(使用insertSubview: belowSubview: 。 当你最小化你的扩展子视图时,你可以从层次结构中删除不可见的UIView。

所以不是很内置,但我认为是最简单的方法。 不知道这是不是你在想什么,希望这是一些帮助。

谨防由克里斯那布哈德(Krishnabhadra)提供的作为解决scheme的代码:

 [[yourSuperView subviews]makeObjectsPerformSelector:@selector(setUserInteractionEnabled:) withObject:[NSNumber numberWithBool:FALSE]]; 

这在所有情况下都不起作用,因为[yourSuperView子视图]只给出超视图的直接子视图。 要使其工作,您将不得不在所有子视图上recursion迭代:

 -(void) disableRecursivelyAllSubviews:(UIView *) theView { theView.userInteractionEnabled = NO; for(UIView* subview in [theView subviews]) { [self disableRecursivelyAllSubviews:subview]; } } -(void) disableAllSubviewsOf:(UIView *) theView { for(UIView* subview in [theView subviews]) { [self disableRecursivelyAllSubviews:subview]; } } 

现在调用disableAllSubviewsOf将做你想做的事情。

如果你有很深的观点,用lxt解决scheme可能会更好。

我会做一个自定义透明buttonsuperView相同的框架。 然后,在那个button的顶部,我会把视图,应该接受用户接触。 button将吞下所有的触摸和视图背后将不会收到任何触摸事件,但button顶部的查看将正常接触。

像这样的东西:

 - (void)disableTouchesOnView:(UIView *)view { UIButton *ghostButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)]; [ghostButton setBackgroundColor:[UIColor clearColor]]; ghostButton.tag = 42; // Any random number. Use #define to avoid putting numbers in code. [view addSubview:ghostButton]; } 

还有一个启用parentView的方法。

 - (void)enableTouchesOnView:(UIView *)view { [[view viewWithTag:42] removeFromSuperview]; } 

因此,要禁用您的parentViev中的parentViev所有视图,我会这样做:

 YourView *yourView = [[YourView alloc] initWithCustomInitializer]; // It is important to disable touches on the parent view before adding the top most view. [self disableTouchesOnView:parentView]; [parentView addSubview:yourView]; 

只要parentView.UserInteractionEnabled = NO会做的工作。 父视图将禁止所有视图的子视图上的用户交互。 但启用它不会启用所有子视图(默认UIImageView不可交互)。 所以一个简单的方法是find父视图并使用上面的代码,并且不需要迭代所有子视图来执行select器。

setUserInteractionEnabled = NO您要禁用的视图

我会给我2美分这个问题。 迭代运行userInteractionEnabled = false是一种方法。 另一种方法是添加一个像下面这样的UIView。

EZEventEater.h

 #import <UIKit/UIKit.h> @interface EZEventEater : UIView @end 

EZEventEater.m

 #import "EZEventEater.h" @implementation EZEventEater - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.backgroundColor = [UIColor clearColor]; self.userInteractionEnabled = false; } return self; } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //EZDEBUG(@"eater touched"); } - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { } 

在你的代码中,添加EZEventEater视图来覆盖所有可能阻止触摸事件的视图。 无论何时您想要将触摸事件屏蔽到这些视图,只需致电

 eater.userInteractionEnabled = YES; 

希望这有帮助。

对于我的应用程序,我认为这将足以禁用导航到应用程序的其他选项卡(在有限的时间内,而我正在做一些处理):

 self.tabBarController.view.userInteractionEnabled = NO; 

另外,我禁用了当前的视图控制器 –

 self.view.userInteractionEnabled = NO; 

(顺便说一句,这里提出的recursion解决scheme在我的应用程序中有奇怪的效果。禁用似乎工作正常,但重新启用有奇怪的效果 – 一些用户界面不renabled)。

我有同样的问题,但上述解决scheme没有帮助。 然后我注意到,调用super.touchesBegan(...)是问题。 删除这个事件后,只能处理最顶层的视图。

我希望这对任何人都有帮助。

添加一个TapGestureRecognizer到你的“背景视图”(半透明的“灰色”你的正常界面),并将其设置为“取消触摸视图”,而无需添加任何操作。

 let captureTaps = UITapGestureRecognizer() captureTaps.cancelsTouchesInView = true dimmedOverlay?.addGestureRecognizer(captureTaps)