如何从UIScrollView窃取触摸?

今天在我的创作时间,我做了一些非常全面的研究,如何从UIScrollView中窃取触摸,并立即将它们发送到特定的子视图,同时保持其他滚动视图的默认行为。 考虑在UITableView中有一个UIPickerView。 默认行为是,如果您将手指拖动到选取器视图上,滚动视图将滚动并且选取器视图将保持不变。

我尝试的第一件事是重写

- (BOOL)touchesShouldCancelInContentView:(UIView *)view 

并且不允许UIScrollView取消select器视图内的触摸。 这工作,但它有一个不愉快的副作用。 您希望拾取器视图立即作出响应,因此您将不得不将delaysContentTouches设置为NO。 问题是你不希望表格视图的其余部分立即作出响应,因为如果这样的话,表格视图单元格在滚动开始之前总是会高亮几毫秒。

我尝试的第二件事是重写

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

因为我已经读过滚动视图总是返回自己,所以它会“窃取”其子视图中的触摸,并且如果它们对滚动视图不感兴趣,那么将它们发送到子视图。 但是,这不再是事实。 UIScrollView的hitTest的默认实现:withEvent:实际返回应该接收触摸的子视图。 相反,它使用手势识别器来拦截触摸。

所以我尝试的第三件事是实现我自己的手势识别器,并导致它失败,如果触摸是在select器视图之外,否则成功。 然后我设置所有滚动视图的手势识别器失败,除非我的手势识别器失败,使用下面的代码:

 for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers) { [gestureRecognizer requireGestureRecognizerToFail:myRecognizer]; } 

这实际上是从滚动视图中窃取触摸,但是拾取器视图从不接收它们。 所以我虽然也许我可以发送我的手势识别器收到的所有触摸使用此代码:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) [touch.view touchesBegan:touches withEvent:event]; } 

上面的代码是一个简化版本。 我还要确保视图是一个select器视图(或其中一个子视图),并为上述手势识别器设置适当的状态。 我也做了同样的取消,结束和移动。 但是,select器视图仍然没有响应。

在回到我的正常工作之前,我还尝试了最后一件事。 在我广泛的search期间,我读了嵌套的UIScrollViews,从3.x开始魔术般的工作,所以我尝试把我的select器视图放在一个嵌套的UIScrollView中,并设置下面的属性:

 scrollView.delaysContentTouches = NO; scrollView.canCancelContentTouches = NO; 

正如人们所期望的那样,外层滚动视图不会将内​​层滚动视图与处理拾取器视图的任何内容视为不同,因此内层滚动视图不会接收到触摸。 我认为这是一个很长的一步,但实施起来很简单,所以我认为值得一试。

我所知道的是,UIScrollView有一个名为UIScrollViewDelayedTouchesBeganGestureRecognizer的手势识别器,截取触摸并在150(?)ms之后发送到适当的子视图。 我想我应该能够写一个类似的识别器,导致滚动视图的默认识别器失败,而不是拖延触摸立即将他们发送到select器视图。 所以,如果有人知道如何写这样的识别器,请让我知道,如果你有任何其他的解决scheme,你也非常欢迎分享。

感谢你阅读整个问题,即使你不知道答案,你仍然可以提出这个问题,以便得到更多的关注(希望有人可以回答)。 谢谢! 🙂

有时候你必须提出这个问题才能find答案。 丹·雷有一个类似的问题,并用一个非常不同的解决scheme来解决它。

 - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView* result = [super hitTest:point withEvent:event]; if ([result.superview isKindOfClass:[UIPickerView class]]) { self.scrollEnabled = NO; } else { self.scrollEnabled = YES; } return result; } 

我已经testing了代码,它也适用于我。 但是,这并不是真的从滚动视图中窃取触摸,所以如果有人知道如何真正窃取将是伟大的触摸。

来源: UITickViewView里面的UIPickerView没有收到拖动触摸

有点晚了,但我发现这个解决scheme: http : //www.cocoanetics.com/2010/06/hacking-uiscrollview-gesture-recognizers/适用于我