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

在左图中,内部的垂直拖动Scrollview B应该移动Scrollview A,Scrollview B不应该是可滚动的(但它仍然需要能够接收触摸/点击).一旦Scrollview A达到它的最大范围(当Scrollview B到达屏幕顶部时),Scrollview B则应滚动.这需要一个连续的动作.
我试图从' 委托方法切换ScrollView B' ,但这似乎不是一个可行的解决方案,因为它不能在一个连续的动作中工作(例如:用户需要在到达顶部后再次释放和触摸屏幕).scrollEnabledScrollView AscrollViewDidScroll:Scrollview B
实现这一点的最佳方法是什么才能在一个连续的运动中起作用?
我通过以下方式解决了这个问题。我对此并不是很满意,因为它在我看来太复杂了,但它确实有效(请注意,下面的代码是我的代码的简化版、未经测试的版本,这是由于不同的 UI 更复杂):
\n\n我有 3 个控制滚动的属性:
\n\n@property (nonatomic, assign) CGFloat currentPanY;\n@property (nonatomic, assign) BOOL scrollA;\n@property (nonatomic, assign) BOOL scrollB;\nRun Code Online (Sandbox Code Playgroud)\n\n两步滚动:
\n\n禁用 B 的滚动,并启用 A 的滚动。
\n这允许滚动 A 。
当 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}\nRun Code Online (Sandbox Code Playgroud)\n\n这会产生以下效果:
\n当 A 向上滚动时,它将在达到其最大尺寸时停止滚动。然而,B 将不会开始滚动,因为 A 的平移手势识别器不会将其动作转发到 B 的平移手势识别器。因此,必须抬起手指并开始第二次滚动。然后,B将滚动。这给出了两步滚动。
连续滚动:
\n\n为了连续滚动,B 必须滚动,同时 A 开始滚动的手指继续向上移动。为了检测到这一点,我在 A 上添加了另一个平移手势识别器,并使其能够与 A 和 B 的内置手势识别器同时检测手势:
\n\n - (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UISwipeGestureRecognizer *)otherGestureRecognizer {\n return YES;\n}\nRun 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} \nRun Code Online (Sandbox Code Playgroud)\n\n还有一个缺点:
\n如果你开始滚动,抬起手指,让scrollView减速,它的行为就像两阶段滚动,因为附加的平移手势识别器不会\xe2\x80\x99识别任何平移手势。
小智 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)
滚动视图 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)