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

时间:2011-03-23 11:56:56

标签: iphone ios cocoa-touch uiview user-interaction

我有一个包含多个子视图的视图。当用户点击子视图时,子视图的大小会扩展到大部分屏幕,但其他一些子视图仍然可以在下面看到。

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

11 个答案:

答案 0 :(得分:53)

希望这有帮助...

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

将禁用视图的直接子视图的userInteraction。然后将userInteraction提供给您想要的唯一视图

yourTouchableView.setUserInteraction = TRUE;

编辑:

似乎在iOS中禁用父视图上的userInteraction不会禁用其子项上的userInteraction .. 所以上面的代码(我的意思是 makeObjectsPerformSelector: 的代码将会仅用于禁用父级直接子视图的userInteraction ..

请参阅用户madewulf的回答,递归获取所有子视图并禁用所有子视图的用户交互。或者,如果您需要在项目的许多位置禁用此视图的userInteraction,您可以对UIView进行分类以添加该功能..这样的事情会做..

@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建议在所有视图之上添加一个不可见的视图是另一种方法。

答案 1 :(得分:45)

有几种方法可以做到这一点。您可以遍历所有其他子视图并设置userInteractionEnabled = NO,但如果您有很多其他视图,那么这不太理想(毕竟,您必须随后将它们全部重命名)。

我这样做的方法是创建一个不可见的UIView,它是整个屏幕的大小,可以“阻止”转到其他视图的所有触摸。有时这实际上是不可见的,有时我可能将其设置为黑色,alpha值为0.3左右。

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

所以不是内置的,但我认为最简单的方法。不确定这是否是你已经想到的,希望它有所帮助。

答案 2 :(得分:8)

谨防Krishnabhadra给出的解决方案代码:

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

这不适用于所有情况,因为[yourSuperView子视图]仅提供超视图的直接子视图。要使其工作,您必须以递归方式迭代所有子视图:

-(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的解决方案可能会更好。

答案 3 :(得分:5)

我会通过将自定义透明按钮放在与superView相同的框架上来完成此操作。然后在该按钮的顶部,我会放置应该接受用户触摸的视图。 按钮会吞下所有触摸,其背后的视图将不会收到任何触摸事件,但按钮顶部的视图将正常接收触摸。

这样的事情:

- (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后面的yourView中的所有视图,我会这样做:

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];

答案 4 :(得分:4)

只需parentView.UserInteractionEnabled = NO即可完成工作。  父视图将在所有视图的子视图中禁用用户互动。但是启用它不会启用所有子视图(默认情况下UIImageView不可交互)。所以一个简单的方法是找到父视图并使用上面的代码,并且不需要迭代所有子视图来执行选择器。

答案 5 :(得分:2)

我会给这个问题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;

希望这有用。

答案 6 :(得分:1)

将TapGestureRecognizer添加到您的&#34;背景视图&#34; (半透明的&#34;灰色&#34;您的正常界面)并将其设置为&#34;取消触摸视图&#34;,而不添加操作。

UCPDate Date Sample Passage CellPlated Days CellCount Squares Volume VolPlated 
150901 150915 P1.X.1 1 25000 4 125 4 1,40 125 
150901 150916 P1.X.1 2 25000 4 124 4 1,40 124 
150901 150917 P1.X.1 3 25000 3 153 4 1,40 153 
150901 150915 P1.X.2 1 25000 4 176 4 1,40 176 
150901 150916 P1.X.2 2 25000 2 124 4 1,40 124 
150901 150917 P1.X.2 3 25000 3 135 4 1,40 135 
150901 150915 P1.X.3 1 25000 4 135 4 1,40 135 
150901 150916 P1.X.3 2 25000 2 142 4 1,40 142 
150901 150917 P1.X.3 3 25000 4 175 4 1,40 175 
150901 150915 P1.X.4 1 25000 5 157 4 1,40 157 
150901 150916 P1.X.4 2 25000 6 143 4 1,40 143 
150901 150917 P1.X.4 3 25000 4 143 4 1,40 143 
150903 150915 P1.X.1 1 25000 4 125 4 1,40 125 
150903 150916 P1.X.1 2 25000 4 124 4 1,40 124 
150903 150917 P1.X.1 3 25000 3 153 4 1,40 153 
150903 150915 P1.X.2 1 25000 4 176 4 1,40 176 
150903 150916 P1.X.2 2 25000 2 124 4 1,40 124 
150903 150917 P1.X.2 3 25000 3 135 4 1,40 135 
150903 150915 P1.X.3 1 25000 4 135 4 1,40 135 
150903 150916 P1.X.3 2 25000 2 142 4 1,40 142 
150903 150917 P1.X.3 3 25000 4 175 4 1,40 175 
150903 150915 P1.X.4 1 25000 5 157 4 1,40 157 
150903 150916 P1.X.4 2 25000 6 143 4 1,40 143 
150903 150917 P1.X.4 3 25000 4 143 4 1,40 143

答案 7 :(得分:0)

您要禁用的视图上的

setUserInteractionEnabled = NO

答案 8 :(得分:0)

对于我的应用,我认为禁用导航到应用的其他标签就足够了(在有限的时间内,我正在进行一些处理):

self.tabBarController.view.userInteractionEnabled = NO;

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

self.view.userInteractionEnabled = NO;

(顺便说一句,这里提出的递归解决方案在我的应用程序中有奇怪的效果。禁用似乎工作正常,但重新启用具有奇怪的效果 - 一些UI不能重命名。)

答案 9 :(得分:0)

在Swift 5中,我通过在顶部(突出显示的一个)顶部放置一个视图并进行设置来实现此行为:

myView.isUserInteractionEnabled = true

这不会让触摸通过它,从而忽略了点击。

enter image description here

答案 10 :(得分:-1)

我遇到了同样的问题,但上述解决方案没有帮助。 我接着注意到了 super.touchesBegan(...)就是问题所在。 删除后,事件仅由最顶层视图处理。

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