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

use*_*435 26 iphone scroll uitableview uiscrollview ios

我有两个嵌套的UIScrollViews,都在垂直方向滚动.在允许内部scrollview滚动之前,我需要外部scrollview首先滚动到它的最大范围.在外部scrollview达到其最大范围之前,内部scrollview不应该是可滚动的.这是一个例子: 嵌套的Scrollviews图

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

我试图从' 委托方法切换ScrollView B' ,但这似乎不是一个可行的解决方案,因为它不能在一个连续的动作中工作(例如:用户需要在到达顶部后再次释放和触摸屏幕).scrollEnabledScrollView AscrollViewDidScroll:Scrollview B

实现这一点的最佳方法是什么才能在一个连续的运动中起作用?

Rei*_*ner 5

我通过以下方式解决了这个问题。我对此并不是很满意,因为它在我看来太复杂了,但它确实有效(请注意,下面的代码是我的代码的简化版、未经测试的版本,这是由于不同的 UI 更复杂):

\n\n

我有 3 个控制滚动的属性:

\n\n
@property (nonatomic, assign) CGFloat currentPanY;\n@property (nonatomic, assign) BOOL    scrollA;\n@property (nonatomic, assign) BOOL    scrollB;\n
Run Code Online (Sandbox Code Playgroud)\n\n

两步滚动:

\n\n

禁用 B 的滚动,并启用 A 的滚动。
\n这允许滚动 A 。

\n\n

当 A 到达其最大位置时,禁用 A 的滚动,并启用 B 的滚动:

\n\n
-(void)scrollViewDidScroll: (UIScrollView *)scrollView {\n    if (scrollView.contentOffset.y >= self.maxScrollUpOffset) {\n        [scrollView setContentOffset:CGPointMake(0, self.maxScrollUpOffset) animated:NO];        \n        self.scrollviewA.scrollEnabled = NO;\n        self.scrollviewB.scrollEnabled = YES;\n        self.scrollB = YES;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会产生以下效果:
\n当 A 向上滚动时,它将在达到其最大尺寸时停止滚动。然而,B 将不会开始滚动,因为 A 的平移手势识别器不会将其动作转发到 B 的平移手势识别器。因此,必须抬起手指并开始第二次滚动。然后,B将滚动。这给出了两步滚动。

\n\n

连续滚动:

\n\n

为了连续滚动,B 必须滚动,同时 A 开始滚动的手指继续向上移动。为了检测到这一点,我在 A 上添加了另一个平移手势识别器,并使其能够与 A 和 B 的内置手势识别器同时检测手势:

\n\n
 - (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer {\n    return YES;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这个附加的平移手势识别器的操作中,我计算达到 A 的滚动限制后手指向上移动的距离。通过这个距离,B 然后以编程方式滚动:

\n\n
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)recognizer {\n    if (recognizer.state != UIGestureRecognizerStateChanged) {\n        self.currentPanY = 0;\n        self.scrollB = NO;\n        self.scrollA = NO;\n    } else {\n        CGPoint currentTranslation = [recognizer translationInView:self.scrollviewA];\n        CGFloat currentYup = currentTranslation.y;\n\n        if (self.scrollA || self.scrollB) {\n            if (self.currentPanY == 0) {\n                self.currentPanY = currentYup;\n            }\n\n            CGFloat additionalYup = self.currentPanY - currentYup;\n            if (self.scrollA) {\n                CGFloat offset = self.scrollviewA.scrollUpOffset + additionalYup;\n                if (offset >= 0) {\n                    self.scrollviewA.contentOffset = CGPointMake(0, offset);\n                } else {\n                    self.scrollviewA.contentOffset = CGPointZero;\n                }\n            } else if (self.scrollB){\n                self.scrollviewB.contentOffset = CGPointMake(0, additionalYup);\n            }\n        }\n    }\n}  \n
Run Code Online (Sandbox Code Playgroud)\n\n

还有一个缺点:
\n如果你开始滚动,抬起手指,让scrollView减速,它的行为就像两阶段滚动,因为附加的平移手势识别器不会\xe2\x80\x99识别任何平移手势。

\n


小智 5

就我而言,我解决了外部 ScrollView 的子类化 UIScrollView 问题。

class MYOuterScrollView: UIScrollView, UIGestureRecognizerDelegate
{
    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool
    {
        return true
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool
    {
         return true
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*son 1

滚动视图 A 的手势识别器需要传递给滚动视图 B 的手势识别器才能进行连续运动,我确信这是不可能的。为什么不将两个滚动视图的内容结合起来,然后你就会有一个连续的动作。这段代码将把scrollView A和B的内容合并到A中。

UIScrollView* scrollViewA = ...;
UIScrollView* scrollViewB = ...;
NSArray* subviews = scrollViewB.subviews;
for (int i = 0; i < subviews.count; i++)
{
    UIView* subview = [subviews objectAtIndex:i];
    CGRect frame = subview.frame;
    frame.origin.y += scrollViewA.contentSize.height;
    subview.frame = frame;
    [scrollViewA addSubview:subview];
}
CGSize size = scrollViewA.contentSize;
size.height += scrollViewB.contentSize.height;
scrollViewA.contentSize = size;
Run Code Online (Sandbox Code Playgroud)