32

我认为当一个视图被触摸或点击时,它的处理程序首先被调用,然后它的超级视图的处理程序被调用(向上传播)。

但是,如果超级视图userInteractionEnabled设置为 NO,那么所有子视图和后代也被禁用以进行用户交互,这是真的吗?如果我们只想禁用主视图但不想禁用子视图怎么办?

4

4 回答 4

35

您可以覆盖hitTest(_:withEvent:)以忽略视图本身,但仍对其子视图进行触摸。

class ContainerStackView : UIStackView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let result = super.hitTest(point, with: event)
        if result == self { return nil }
        return result
    }
}
于 2016-06-29T01:56:13.500 回答
29

如果这可能有帮助,我在 Matt Neuburg 的 Programming iOS 5 中发现了这一点,p。467:

userInteractionEnabled

如果设置为 NO,则此视图(及其子视图)将被排除在接收触摸之外。触及此视图或其子视图之一“落入”其后面的视图。

此外,Apple 的 iOS 事件处理指南说:

窗口对象使用命中测试和响应者链来找到接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用 hitTest:withEvent:;此方法通过在视图层次结构中返回 YES 的每个视图上递归调用 pointInside:withEvent: 来继续,沿着层次结构向下进行,直到找到在其范围内发生触摸的子视图。该视图成为命中测试视图。

和 Programming iOS 5 by Matt Neuburg, p.485 提到如果一个视图被标记userInteractionEnabledNO, 或hidden,YES或不透明度接近 0, 那么视图和它的子视图将不会被遍历HitTest(因此不考虑任何触摸) .

更新:如果我们考虑其他场景中的亲子情况,我想它也可以这样工作。例如,在 HTML 中,如果有 adiv并且 this 下都有孩子div,现在 thisdiv设置为display: none,那么所有孩子都不显示是有道理的。因此,如果将父级设置为不与用户交互,那么子级也不与用户交互也是有意义的。

于 2012-06-05T06:19:28.730 回答
17

你不能那样做,

相反,您将更改视图的排列,如下所示:

Main View -> subViews

Container View -> Main View that you want to set as inactive
               -> other views that you want to still be active

所以你当前的主视图和你当前的子视图将成为兄弟,新容器视图的子视图

于 2012-06-04T12:07:35.370 回答
3

第一种方法

- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
  if ([touch.view.superview isKindOfClass:[SuperViewParent class]]) return FALSE;
  return TRUE;
}

第二种方法

UITapGestureRecognizer *r = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(agentPickerTapped:)];
    r.cancelsTouchesInView = NO;
    [agentPicker addGestureRecognizer:r];
于 2014-10-24T07:28:12.177 回答