我有两个嵌套的 UIScrollView,它们都在垂直方向滚动。在允许内部 ScrollView 滚动之前,我需要先将外部 ScrollView 滚动到它的最大范围。在外部 ScrollView 达到其最大范围之前,内部 ScrollView 不应滚动。这是一个例子:
在左图中,Scrollview B
内的垂直拖动应该移动 Scrollview A
而 Scrollview B
不应该是可滚动的(但它仍然需要能够接收触摸/点击)。一旦 Scrollview A
达到它的最大范围(当 Scrollview B
到达屏幕顶部时),Scrollview B
应该滚动。这需要以一个连续的 Action 进行。
我试图从 ScrollView A
的 scrollViewDidScroll:
委托(delegate)中切换 ScrollView B
的 scrollEnabled
方法,但这似乎不是一个可行的解决方案,因为它不能在一个连续的 Action 中工作(例如:用户需要在 Scrollview B
到达屏幕顶部后松开并再次触摸).
实现这一点的最佳方式是什么,以便在一个连续的 Action 中工作?
最佳答案
我通过以下方式解决了这个问题。我对它不是很满意,因为它在我看来太复杂了,但它确实有效(请注意下面的代码是我代码的一个简化的、未经测试的版本,这是由于不同的用户界面更复杂):
我有 3 个控制滚动的属性:
@property (nonatomic, assign) CGFloat currentPanY;
@property (nonatomic, assign) BOOL scrollA;
@property (nonatomic, assign) BOOL scrollB;
两步滚动:
为 B 禁用滚动,为 A 启用滚动。
这允许滚动 A 。
当 A 到达其最大位置时,禁用 A 的滚动,并启用 B 的滚动:
-(void)scrollViewDidScroll: (UIScrollView *)scrollView {
if (scrollView.contentOffset.y >= self.maxScrollUpOffset) {
[scrollView setContentOffset:CGPointMake(0, self.maxScrollUpOffset) animated:NO];
self.scrollviewA.scrollEnabled = NO;
self.scrollviewB.scrollEnabled = YES;
self.scrollB = YES;
}
}
这会产生以下效果:
当 A 向上滚动时,它会在达到最大尺寸时停止滚动。但是 B 不会开始滚动,因为 A 的平移手势识别器不会将其 Action 转发给 B 的平移手势识别器。因此必须抬起手指并开始第二次滚动。然后,B 将滚动。这给出了两步滚动。
连续滚动:
对于连续滚动,B 必须滚动,同时开始滚动 A 的手指继续向上移动。为了检测这一点,我在 A 中添加了一个进一步的平移手势识别器,并使其能够与 A 和 B 的内置手势识别器同时检测手势:
- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer {
return YES;
}
在这个额外的平移手势识别器的 Action 中,我计算了在达到 A 的滚动限制后手指向上移动的距离。通过这个距离,B 然后以编程方式滚动:
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state != UIGestureRecognizerStateChanged) {
self.currentPanY = 0;
self.scrollB = NO;
self.scrollA = NO;
} else {
CGPoint currentTranslation = [recognizer translationInView:self.scrollviewA];
CGFloat currentYup = currentTranslation.y;
if (self.scrollA || self.scrollB) {
if (self.currentPanY == 0) {
self.currentPanY = currentYup;
}
CGFloat additionalYup = self.currentPanY - currentYup;
if (self.scrollA) {
CGFloat offset = self.scrollviewA.scrollUpOffset + additionalYup;
if (offset >= 0) {
self.scrollviewA.contentOffset = CGPointMake(0, offset);
} else {
self.scrollviewA.contentOffset = CGPointZero;
}
} else if (self.scrollB){
self.scrollviewB.contentOffset = CGPointMake(0, additionalYup);
}
}
}
}
还有一个缺点:
如果您开始滚动,抬起手指,然后让 scrollView 减速,它将表现得像 2 阶段滚动,因为额外的平移手势识别器不会识别任何平移手势。
关于ios - 处理向同一方向滚动的嵌套 UIScrollViews 的触摸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27451041/