让两个UIScrollView跟着彼此滚动

我将如何使两个滚动视图跟随彼此滚动?

例如,我在屏幕左侧有一个滚动视图(A),其内容可以上下滚动,但不能左右滚动。 滚动视图B与A的向上和向下匹配,但也可以向左和向右滚动。 滚动视图A始终在屏幕上。

----------------------------------------------------------- | | | | | | | | | | A | B | | | | | scrolls | | | up & down | scrolls all directions | | | | ----------------------------------------------------------- 

我该如何做,所以上下滚动(任一视图)也使其他视图滚动在相同的上下方向? 还是有另一种方法来做到这一点?

将滚动视图A的代理设置为您的视图控制器…然后…

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGPoint offset = scrollViewB.contentOffset; offset.y = scrollViewA.contentOffset.y; [scrollViewB setContentOffset:offset]; } 

如果你想同时关注对方,那么为它们设置委托并使用…

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if([scrollView isEqual:scrollViewA]) { CGPoint offset = scrollViewB.contentOffset; offset.y = scrollViewA.contentOffset.y; [scrollViewB setContentOffset:offset]; } else { CGPoint offset = scrollViewA.contentOffset; offset.y = scrollViewB.contentOffset.y; [scrollViewA setContentOffset:offset]; } } 

以上可以被重构为具有两个滚动视图并且彼此匹配的方法。

 - (void)matchScrollView:(UIScrollView *)first toScrollView:(UIScrollView *)second { CGPoint offset = first.contentOffset; offset.y = second.contentOffset.y; [first setContentOffset:offset]; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if([scrollView isEqual:scrollViewA]) { [self matchScrollView:scrollViewB toScrollView:scrollViewA]; } else { [self matchScrollView:scrollViewA toScrollView:scrollViewB]; } } 

Swift 3版本:

  func scrollViewDidScroll(_ scrollView: UIScrollView) { if scrollView == scrollViewA { self.synchronizeScrollView(scrollViewB, toScrollView: scrollViewA) } else if scrollView == scrollViewB { self.synchronizeScrollView(scrollViewA, toScrollView: scrollViewB) } } func synchronizeScrollView(_ scrollViewToScroll: UIScrollView, toScrollView scrolledView: UIScrollView) { var offset = scrollViewToScroll.contentOffset offset.y = scrolledView.contentOffset.y scrollViewToScroll.setContentOffset(offset, animated: false) } 

我尝试了西蒙李在iOS 11的答案。它的工作,但不是很好。 这两个滚动视图是同步的,但使用他的方法,滚动视图将失去惯性效果(当它释放你的手指后继续滚动)和弹跳效果。 我认为这是因为通过setContentOffset(offset, animated: false)方法设置contentOffset会导致scrollViewDidScroll(_ scrollView: UIScrollView)委托方法的循环调用(请参阅此问题 )

以下是在iOS 11上为我工作的解决scheme:

  // implement UIScrollViewDelegate method func scrollViewDidScroll(_ scrollView: UIScrollView) { if scrollView == self.scrollViewA { self.syncScrollView(self.scrollViewB, toScrollView: self.scrollViewA) } else if scrollView == self.scrollViewB { self.syncScrollView(self.scrollViewA, toScrollView: scrollViewB) } } func syncScrollView(_ scrollViewToScroll: UIScrollView, toScrollView scrolledView: UIScrollView) { var scrollBounds = scrollViewToScroll.bounds scrollBounds.origin.y = scrolledView.contentOffset.y scrollViewToScroll.bounds = scrollBounds } 

因此,不是设置contentOffset而是使用bounds属性将另一个scrollView与用户滚动的scrollView进行同步。 这样,委托方法scrollViewDidScroll(_ scrollView: UIScrollView)就不会被循环调用,而且滚动发生得非常平滑,并且与单个滚动视图一样具有惯性和弹跳效果。