ios UIView——“启用用户交互”在父级上为假,而在子级上为真?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5887305/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:48:42  来源:igfitidea点击:

UIView -- "user interaction enabled" false on parent but true on child?

cocoa-touchiosuiview

提问by morgancodes

It appears that userInteractionEnabled=NO on a parent view will prevent user interaction on all subviews. Is this correct? Is there any way around this?

父视图上的 userInteractionEnabled=NO 似乎会阻止所有子视图上的用户交互。这样对吗?有没有办法解决?

采纳答案by lazycs

That's correct, userInteractionEnabled set to NO on a parent view will cascade down to all subviews. If you need some subviews to have interaction enabled, but not others, you can separate your subviews into two parent views: one with userInteractionEnabled = YES and the other NO. Then put those two parent views in the main view.

没错,在父视图上将 userInteractionEnabled 设置为 NO 将向下级联到所有子视图。如果您需要一些子视图启用交互,而不是其他,您可以将子视图分成两个父视图:一个 userInteractionEnabled = YES,另一个 NO。然后将这两个父视图放在主视图中。

回答by Ali

You can subclass UIView and override hitTest:withEvent: in a way to pass touch events to a view that you specify (_backView):

您可以继承 UIView 并覆盖 hitTest:withEvent: 以将触摸事件传递给您指定的视图 (_backView):

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *view = [super hitTest:point withEvent:event];

    if (view == self) {
        view = _backView;
    }

    return view;
}

If the touch event was to be handled by this view it would be passed to "_backView" (that can be an IBOutlet so that it can be set using interface builder) ; and if it was to be handled by any child view just return that child (the result of [super hitTest:point withEvent:event];)

如果触摸事件由该视图处理,它将被传递给“_backView”(它可以是一个 IBOutlet,以便它可以使用界面构建器进行设置);如果它由任何子视图处理,只需返回该子视图([super hitTest:point withEvent:event];的结果)

This solution is fine as long as you know what view you need to pass the events to; besides don't know if it has problems since we are returning a view (_backView) that is not a subview of the current UIView !! but it worked fine in my case.

只要您知道需要将事件传递到哪个视图,这个解决方案就很好;此外不知道它是否有问题,因为我们返回的视图(_backView)不是当前 UIView 的子视图!但在我的情况下它工作得很好。

A better solution might be the one mentioned in Disable touches on UIView background so that buttons on lower views are clickableThere its mentioned to use -pointInside:withEvent:; compared to previous solution its better in the way that you don't need to specify a '_backView' to receive the events (the event is simply passed to the next view in chain)! drawback might be that we need to perform -pointInside:withEvent:on all subviews (might be of negligible overhead though)

一个更好的解决方案可能是Disable touches on UIView background 中提到的一个, 以便较低视图上的按钮可以点击那里提到使用-pointInside:withEvent:;与之前的解决方案相比,它更好的方式是您不需要指定“_backView”来接收事件(事件只是传递给链中的下一个视图)!缺点可能是我们需要-pointInside:withEvent:在所有子视图上执行(尽管开销可能可以忽略不计)

回答by Chris Prince

I just ran into an odd situation. I have a UIView (call this, V), which has a UIButton as a subview. Call this UIButton, button X. Below is the method I'm using for the target/selector of button X. self below is the view V. The sender parameter is button X.

我刚刚遇到了一个奇怪的情况。我有一个 UIView(称之为 V),它有一个 UIButton 作为子视图。调用这个 UIButton,按钮 X。下面是我用于按钮 X 的目标/选择器的方法。下面的 self 是视图 V。发送方参数是按钮 X。

The situation that's causing me an issue is that if I touch another button on my UI (on the nav bar, call this button Y) and then very quickly touch button X, where the the button Y action disables view V, I still get the touch event sent to button X.

导致我出现问题的情况是,如果我触摸 UI 上的另一个按钮(在导航栏上,调用此按钮 Y),然后非常快速地触摸按钮 X,其中按钮 Y 操作禁用了视图 V,我仍然得到触摸事件发送到按钮 X。

- (void) buttonAction: (UIButton *) sender
{
    NSLog(@"superview: %d", sender.superview.userInteractionEnabled);  
    NSLog(@"button itself: %d", sender.userInteractionEnabled);

    // <snip>
}

Here's the output:

这是输出:

2014-12-19 16:57:53.826 MyApp[6161:960615] superview: 0
2014-12-19 16:57:53.826 MyApp[6161:960615] button itself: 1

2014-12-19 16:57:53.826 MyApp[6161:960615] 超级视图:0
2014-12-19 16:57:53.826 MyApp[6161:960615] 按钮本身:1

That is, the button action occurred and the button's superview had user interaction disabled! And the subview still had user interaction enabled!!

也就是说,按钮动作发生并且按钮的超级视图禁用了用户交互!并且子视图仍然启用了用户交互!!

For those of you thinking that this seems artificial, on my app's UI, running on an iPad (running iOS 8.1.2), this came up by accident in my use of the app. It was not something I was originally tryingto generate.

对于那些认为这似乎是人为的,在我的应用程序的 UI 上,在 iPad(运行 iOS 8.1.2)上运行的人,这是我在使用该应用程序时偶然出现的。这不是我最初试图生成的东西。

Thoughts?

想法?

My current workaround is given below, but it seems really odd that it's necessary!

下面给出了我目前的解决方法,但它的必要性似乎很奇怪!

- (void) buttonAction: (id) sender
{
    NSLog(@"superview: %d", sender.superview.userInteractionEnabled);  
    NSLog(@"button itself: %d", sender.userInteractionEnabled);
    if (! self.userInteractionEnabled) return;

    // <snip>
}

回答by Alfi

I made up a weird solution for this, I had a child view in a tableView cell that I wanted to be touchable but the parent shouldn't have...

我为此制定了一个奇怪的解决方案,我在 tableView 单元格中有一个子视图,我希望可以触摸它,但父视图不应该...

Neither of above solutions worked for me, but I found another solution. Go to storyboard and add a tapGestureRecognizer to the parent view to absorb touches on parent view. Problem solved!

上述解决方案都不适合我,但我找到了另一个解决方案。转到 storyboard 并将 tapGestureRecognizer 添加到父视图以吸收对父视图的触摸。问题解决了!

回答by NeoGER89

I′m doing this in a xib which is my "custom alert controller"-view.

我在 xib 中执行此操作,这是我的“自定义警报控制器”视图。

for (UIView *subview in self.superview.subviews) {

    if (![subview isEqual:self]) {
        subview.userInteractionEnabled = NO;
    }
}