如何禁用触摸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可能会更好。
我会做一个自定义透明button与superView
相同的框架。 然后,在那个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)