我认为当一个视图被触摸或点击时,它的处理程序首先被调用,然后它的超级视图的处理程序被调用(向上传播)。
但是,如果超级视图userInteractionEnabled
设置为 NO,那么所有子视图和后代也被禁用以进行用户交互,这是真的吗?如果我们只想禁用主视图但不想禁用子视图怎么办?
我认为当一个视图被触摸或点击时,它的处理程序首先被调用,然后它的超级视图的处理程序被调用(向上传播)。
但是,如果超级视图userInteractionEnabled
设置为 NO,那么所有子视图和后代也被禁用以进行用户交互,这是真的吗?如果我们只想禁用主视图但不想禁用子视图怎么办?
您可以覆盖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
}
}
如果这可能有帮助,我在 Matt Neuburg 的 Programming iOS 5 中发现了这一点,p。467:
userInteractionEnabled
如果设置为 NO,则此视图(及其子视图)将被排除在接收触摸之外。触及此视图或其子视图之一“落入”其后面的视图。
此外,Apple 的 iOS 事件处理指南说:
窗口对象使用命中测试和响应者链来找到接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用 hitTest:withEvent:;此方法通过在视图层次结构中返回 YES 的每个视图上递归调用 pointInside:withEvent: 来继续,沿着层次结构向下进行,直到找到在其范围内发生触摸的子视图。该视图成为命中测试视图。
和 Programming iOS 5 by Matt Neuburg, p.485 提到如果一个视图被标记userInteractionEnabled
为NO
, 或hidden
,YES
或不透明度接近 0, 那么视图和它的子视图将不会被遍历HitTest
(因此不考虑任何触摸) .
更新:如果我们考虑其他场景中的亲子情况,我想它也可以这样工作。例如,在 HTML 中,如果有 adiv
并且 this 下都有孩子div
,现在 thisdiv
设置为display: none
,那么所有孩子都不显示是有道理的。因此,如果将父级设置为不与用户交互,那么子级也不与用户交互也是有意义的。
你不能那样做,
相反,您将更改视图的排列,如下所示:
Main View -> subViews
到
Container View -> Main View that you want to set as inactive
-> other views that you want to still be active
所以你当前的主视图和你当前的子视图将成为兄弟,新容器视图的子视图
第一种方法
- (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];