父视图上的userInteractionEnabled = NO似乎会阻止用户在所有子视图上进行交互。它是否正确?有没有办法解决这个问题?
答案 0 :(得分:35)
这是正确的,父视图上的userInteractionEnabled设置为NO将向下级联到所有子视图。如果您需要某些子视图以启用交互,而不启用其他子视图,则可以将子视图分成两个父视图:一个使用userInteractionEnabled = YES,另一个使用NO。然后将这两个父视图放在主视图中。
答案 1 :(得分:15)
您可以将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;
}
如果要通过此视图处理触摸事件,它将传递给“_backView”(可以是IBOutlet,以便可以使用界面构建器进行设置);如果要由任何子视图处理,则返回该子项([super hitTest:point withEvent:event]
的结果;)
只要您知道将事件传递给哪个视图,此解决方案就可以了。除了不知道它是否有问题,因为我们返回的视图(_backView)不是当前UIView的子视图!但在我的情况下它运作良好。
更好的解决方案可能是提到的那个
Disable touches on UIView background so that buttons on lower views are clickable提到使用-pointInside:withEvent:
;与之前的解决方案相比,它更好的方式是您不需要指定'_backView'来接收事件(事件只是传递给链中的下一个视图)!缺点可能是我们需要对所有子视图执行-pointInside:withEvent:
(虽然可能忽略了开销)
答案 2 :(得分:2)
我刚遇到一个奇怪的情况。我有一个UIView(称之为V),它有一个UIButton作为子视图。调用此UIButton,按钮X.下面是我用于按钮X的目标/选择器的方法。下面的自身是视图V.发送者参数是按钮X.
导致我出现问题的情况是,如果我触摸我的UI上的另一个按钮(在导航栏上,调用此按钮Y),然后非常快速地触摸按钮X,其中按钮Y动作禁用视图V,I仍然会将触摸事件发送到按钮X.
- (void) buttonAction: (UIButton *) sender
{
NSLog(@"superview: %d", sender.superview.userInteractionEnabled);
NSLog(@"button itself: %d", sender.userInteractionEnabled);
// <snip>
}
这是输出:
2014-12-19 16:57:53.826 MyApp [6161:960615] superview:0
2014-12-19 16:57:53.826 MyApp [6161:960615]按钮本身:1
也就是说,按钮动作发生了,按钮的超级视图禁用了用户交互!子视图仍然启用了用户交互!!
对于那些认为这看似虚假的人,在我的应用程序的UI上,在iPad上运行(运行iOS 8.1.2),这在我使用应用程序时偶然出现了。这不是我原本尝试生成的东西。
思想?
我目前的解决方法如下,但似乎很奇怪,这是必要的!
- (void) buttonAction: (id) sender
{
NSLog(@"superview: %d", sender.superview.userInteractionEnabled);
NSLog(@"button itself: %d", sender.userInteractionEnabled);
if (! self.userInteractionEnabled) return;
// <snip>
}
答案 3 :(得分:0)
我在xib中这样做,这是我的“自定义警报控制器”-view。
for (UIView *subview in self.superview.subviews) {
if (![subview isEqual:self]) {
subview.userInteractionEnabled = NO;
}
}
答案 4 :(得分:0)
为此,我提出了一个怪异的解决方案,在tableView单元格中有一个子视图,我希望该子视图是可触摸的,但父级视图不应该...
以上两种解决方案都不适合我,但我找到了另一种解决方案。 转到情节提要,然后将tapGestureRecognizer添加到父视图以吸收父视图上的触摸。 问题解决了!
答案 5 :(得分:0)
这是解决方案 创建从“ UIView”继承的类,并编写覆盖“内部点”的func
class TTSView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
for view in self.subviews {
if view.isUserInteractionEnabled, view.point(inside: self.convert(point, to: view), with: event) {
return true
}
}
return false
}
}
然后在情节提要或xib中,超级视图必须使用此类