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

Mus*_*sis 43 iphone cocoa-touch user-interaction uiview ios

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

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

Kri*_*dra 53

希望这有帮助......

[[yourSuperView subviews]
   makeObjectsPerformSelector:@selector(setUserInteractionEnabled:)
   withObject:[NSNumber numberWithBool:FALSE]];
Run Code Online (Sandbox Code Playgroud)

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

yourTouchableView.setUserInteraction = TRUE;
Run Code Online (Sandbox Code Playgroud)

编辑:

似乎在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
Run Code Online (Sandbox Code Playgroud)

现在你可以打电话了

[yourSuperView setRecursiveUserInteraction:NO];
Run Code Online (Sandbox Code Playgroud)

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


lxt*_*lxt 46

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

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

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

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

  • 你会怎么做到这一点? (2认同)

mad*_*ulf 8

请注意Krishnabhadra给出的解决方案代码:

[[yourSuperView subviews]makeObjectsPerformSelector:@selector(setUserInteractionEnabled:) withObject:[NSNumber numberWithBool:FALSE]];
Run Code Online (Sandbox Code Playgroud)

这不适用于所有情况,因为[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];
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在打电话disableAllSubviewsOf来做你想做的事.

如果你有一堆深层的视图,那么lxt的解决方案可能更好.


Rob*_*ins 5

将 TapGestureRecognizer 添加到您的“背景视图”(使您的正常界面“变灰”的半透明视图)并将其设置为“取消视图中的触摸”,而不添加操作。

let captureTaps = UITapGestureRecognizer()
captureTaps.cancelsTouchesInView = true
dimmedOverlay?.addGestureRecognizer(captureTaps)
Run Code Online (Sandbox Code Playgroud)


JPe*_*ric 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];
}
Run Code Online (Sandbox Code Playgroud)

以及一种启用该方法的方法parentView.

- (void)enableTouchesOnView:(UIView *)view {
    [[view viewWithTag:42] removeFromSuperview];
}
Run Code Online (Sandbox Code Playgroud)

所以,要禁用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];
Run Code Online (Sandbox Code Playgroud)


小智 5

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