ios - 处理向同一方向滚动的嵌套 UIScrollViews 的触摸

标签 ios iphone uitableview uiscrollview scroll

我有两个嵌套的 UIScrollView,它们都在垂直方向滚动。在允许内部 ScrollView 滚动之前,我需要先将外部 ScrollView 滚动到它的最大范围。在外部 ScrollView 达到其最大范围之前,内部 ScrollView 不应滚动。这是一个例子: Nested Scrollviews Diagram

在左图中,Scrollview B 内的垂直拖动应该移动 Scrollview AScrollview B 不应该是可滚动的(但它仍然需要能够接收触摸/点击)。一旦 Scrollview A 达到它的最大范围(当 Scrollview B 到达屏幕顶部时),Scrollview B 应该滚动。这需要以一个连续的 Action 进行。

我试图从 ScrollView AscrollViewDidScroll: 委托(delegate)中切换 ScrollView BscrollEnabled方法,但这似乎不是一个可行的解决方案,因为它不能在一个连续的 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/

相关文章:

ios - UITableViewCell 自定义分隔符在滚动 ios8 期间消失

ios - 3D触摸快捷方式应用程序:didfinishlaunchingwithoptions:performActionForShortcutItem:执行顺序

ios - 来 self 的 iOS 应用程序的 Alexa 技能套件交互

ios - UIView 从左到右滑动动画有问题?

iphone - iOS 如何决定向哪些对象发送 didReceiveMemoryWarning 消息?

iPhone App 向设备确认身份

iphone - 如何在从 nib 文件加载的 UITableViewCell 上设置标签?

ios - TableViewCell 的 textLabel 和 detailTextLabel 不起作用

iphone - 显示 NSArray 中的每个对象 2 秒

iphone - UITableView 滚动太远并导致奇怪的事情