基本上,这是我的视图层次结构(如果这很难读,我会道歉......我是新来的,所以发布的建议很乐意接受)
- AppControls.xib
-------(UIView)ControlsView
-----------------(UIView)TopBar
----------------- -------------- btn1,btn2,btn3
----------------- UIView)BottomBar
----------------- -------------- slider1 btn1,btn2
--PageContent.xib
-----------------(UIView)ContentView
----------------- -------------- btn1,btn2,btn3
----------------- --------------(UIImageView)FullPageImage
我的情况是,我想隐藏并显示控件,当点击PageContent上的任何地方而不是按钮并且控件显示时,就像iPhone视频播放器一样。但是,当显示控件时,我仍然希望能够单击PageContent上的按钮。
除了最后一点,我完成了所有这些工作。当控件显示控件的背景时,接收触摸事件而不是下面的视图。在ControlsView上关闭用户交互会在其所有子节点上关闭它。
我已尝试在我的ControlsView子类上覆盖HitTest,如下所示,我在类似的帖子中找到了:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *hitView = nil;
NSArray *subviews = [self subviews];
int subviewCount = [subviews count];
for (int subviewIndex = 0; !hitView && subviewIndex < subviewCount; subviewIndex++){
hitView = [[subviews objectAtIndex:subviewIndex] hitTest:point withEvent:event];
}
return hitView;
}
然而,此时我的滑块不起作用,大多数其他按钮也没有用,而且真的,事情开始变得怪异。
所以我的问题很简单:如何让视图的所有子视图都有触摸事件,而超级视图的背景是不可点击的,下面视图上的按钮可以接收触摸事件。
谢谢!
答案 0 :(得分:66)
你很亲密。请勿覆盖-hitTest:withEvent:
。到调用时,事件调度程序已经确定您的层次结构的子树拥有该事件,并且不会查找其他地方。相反,覆盖事件处理管道中先前调用的-pointInside:withEvent:
。这是系统如何询问“嘿视图,你的层次结构中的任何人在此时是否对事件做出响应?”。如果您拒绝,则在可见堆栈中继续进行事件处理。
根据documentation,默认实现只检查该点是否在视图的边界内。
您的策略是当您的任何子视图位于该坐标时说“是”,但当触摸将触及背景时说“不”。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView * view in [self subviews]) {
if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
return YES;
}
}
return NO;
}
答案 1 :(得分:3)
感谢@Ben Zutto,Swift 3解决方案:
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
}
答案 2 :(得分:1)
另一种方法可能是在其他所有内容后面放置一个不可见的全屏按钮,并在被击中时采取适当的行动。
答案 3 :(得分:1)
Ben的回答略有不同,处理与父母之外的孩子。 如果 clipChildren 为YES,那么对于主控制之外但在某个子节点内的点,这不会返回YES。 如果 clipChildren 为NO,则与Ben的相同。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL clipChildren = YES;
if (!clipChildren || [super pointInside:point withEvent:event]) {
for (UIView * view in [self subviews]) {
if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
return YES;
}
}
}
return NO;
}