我认为当触摸或点击视图时,它的处理程序会首先被调用,然后再调用其父视图的处理程序(向上传播)。
但是,如果父视图的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
}
}
此外,苹果的 iOS 事件处理指南也提到:
userInteractionEnabled
如果设置为 NO,此视图(以及其子视图)将不接收触摸事件。在此视图或其子视图上的触摸事件将“穿透”到其后面的视图中。
并且 Matt Neuburg 的《Programming iOS 5》第 485 页提到,如果一个视图的窗口对象使用命中测试和响应者链来查找要接收触摸事件的视图。在命中测试中,窗口在视图层次结构中的最顶层视图上调用 hitTest:withEvent: 方法;该方法通过递归地对每个返回 YES 的视图在其视图层次结构中调用 pointInside:withEvent: 方法进行处理,一直向下遍历视图层次结构,直到找到包含触摸点的子视图。这个视图成为命中测试视图。
userInteractionEnabled
属性为 NO
,或 hidden
属性为 YES
,或者不透明度接近于 0,则该视图及其子视图将不会被 HitTest 遍历(因此不会考虑任何触摸事件)。div
,并且所有的子元素都在这个 div
下面,现在这个 div
被设置为 display: none
,那么所有的子元素都不会显示出来。因此,如果将父级设置为不与用户交互,那么子级不与用户交互也是有道理的。hitTest:withEvent:
方法的人来说,这是一条卓越的信息。我不确定是否需要在父视图层面检查if(subview.userInteractionEnabled)
,但似乎默认的实现会检查自己的userInteractionEnabled
属性。 - user244343你不能这样做,
相反,你可以像以下这样更改视图的排列:
Main View -> subViews
To
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];