使两个 UIScrollView 跟随彼此滚动
我如何使两个滚动视图跟随彼此滚动?
例如,我在屏幕左侧有一个滚动视图(A),其内容可以上下滚动,但不能左右滚动。滚动视图 B 与 A 的上下滚动一致,但也可以左右滚动。滚动视图 A 始终在屏幕上。
-----------------------------------------------------------
| | |
| | |
| | |
| A | B |
| | |
| scrolls | |
| up & down | scrolls all directions |
| | |
-----------------------------------------------------------
我该如何做到这一点,以便(任一视图的)上下滚动也使另一个视图以相同的上下方向滚动?或者还有其他方法可以做到这一点吗?
How would I make two scroll views follow each others scrolling?
For instance, I have a scroll view (A) on the left of a screen, whose contents can scroll up and down, but not left and right. Scroll view B matches the up and down of A, but can also scroll left and right. Scroll view A is always on the screen.
-----------------------------------------------------------
| | |
| | |
| | |
| A | B |
| | |
| scrolls | |
| up & down | scrolls all directions |
| | |
-----------------------------------------------------------
How would I make it so the the up and down scrolling (of either view) also makes the other view scroll in the same up-down direction? Or is there another method to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
将滚动视图 A 的委托设置为您的视图控制器...然后...
如果您希望两者相互跟随,则为它们两个设置委托并使用...
上面可以重构为有一个方法它接受两个滚动视图并将其中一个与另一个相匹配。
Swift 3 版本:
Set the delegate of scroll view A to be your view controller... then have...
If you want both to follow each other, then set delegate for both of them and use...
The above can be refactored to have a method which takes in two scrollviews and matches one to the other.
Swift 3 Version:
我在 iOS 11 上尝试了 Simon Lee 的答案。它有效,但不是很好。两个滚动视图是同步的,但是使用他的方法,滚动视图会失去惯性效果(松开手指后继续滚动)和弹跳效果。我认为这是因为通过
setContentOffset(offset,animated: false)
方法设置contentOffset
会导致scrollViewDidScroll(_scrollView: UIScrollView) 的循环调用)
委托方法(参见 这个问题)这是在 iOS 11 上对我有用的解决方案:
所以不要设置 < code>contentOffset 我们使用
bounds
属性将另一个滚动视图与用户滚动的滚动视图同步。这样,委托方法scrollViewDidScroll(_scrollView: UIScrollView)
就不会被循环调用,并且滚动会非常平滑地进行,并且与单个滚动视图一样具有惯性和弹跳效果。I tried the Simon Lee's answer on iOS 11. It worked but not very well. The two scroll views was synchronized, but using his method, the scroll views would lost the inertia effect(when it continue to scroll after you release your finger) and the bouncing effect. I think it was due to the fact that setting the
contentOffset
throughsetContentOffset(offset, animated: false)
method causes cyclic calls of thescrollViewDidScroll(_ scrollView: UIScrollView)
delegate's method(see this question)Here is the solution that worked for me on iOS 11:
So instead of setting
contentOffset
we are usingbounds
property to sync the other scrollView with the one that was scrolled by the user. This way the delegate methodscrollViewDidScroll(_ scrollView: UIScrollView)
is not called cyclically and the scrolling happens very smooth and with inertia and bouncing effects as with a single scroll view.Swift 5.4 // Xcode 13.1
对我来说完美的工作如下:
UIGestureRecognizer
委托gestureRecognizer(_:shouldRecognizeSimultaneouslyWith :)
GestureRecognizerDelegate
方法希望这有帮助!
Swift 5.4 // Xcode 13.1
What has worked flawlessly for me was the following:
UIGestureRecognizer
delegategestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
GestureRecognizerDelegate
methodHope this helps!
伙计们,我知道问题已经得到解答,但决定在这里与大家分享我解决类似问题的方法,因为我相信这是一个非常干净的解决方案。基本上我必须让三个集合视图一起滚动,我所做的是我做了一个 自定义
UICollectionView
子类名为SharedOffsetCollectionView
,当您将此类设置为故事板中的集合视图,或者直接从代码实例化它,您可以让所有实例以相同的方式滚动。因此,使用 SharedOffsetCollectionView 时,应用程序中此类的所有集合视图实例将始终以相同的方式滚动。在我看来,这是一个干净的解决方案,因为它需要在视图控制器中添加零逻辑,它全部包含在这个外部类中,您只需将集合视图的类设置为 SharedOffsetCollectionView 并你完成了。
相同的方法可以轻松地转移到
UITableView
和UIScrollView
s希望这对您有所帮助。 :)
我的解决方案是用以下语言编写的:
Swift 5.2,XCode 11.4.1
Guys i know the question is answered, but decided to share with you here my approach for solving a similar issue that i had, because i believe it is a pretty clean solution. Basically i had to make three collection views scroll together, and what i did, is i made a custom
UICollectionView
subclass calledSharedOffsetCollectionView
, that when you set this class to a collection view in storyboards or you instantiate it from code directly, you can have all instances scroll the same.So with
SharedOffsetCollectionView
all collection view instances of this class in your app, will scroll the same always. In my opinion it is a clean solution because it requires adding zero logic in your view controllers, it is all contained in this external class, you just have to set the class of your collection view to beSharedOffsetCollectionView
and you are done.The same approach could easily be transferred to
UITableView
s andUIScrollView
sHope that is helpful to some you. :)
My solution is written in:
Swift 5.2, XCode 11.4.1
最重要的答案对我来说不太有效,因为我遇到了
scrollViewDidScroll
的循环调用。发生这种情况是因为设置滚动视图的内容偏移量也会调用scrollViewDidScoll。我通过在它之间放置一个锁来解决这个问题,该锁是根据用户是否拖动滚动视图来设置的,因此通过设置内容偏移量不会发生同步:可以根据有多少个内容来重构此代码滚动视图的使用取决于它们的所有者。我不建议让一个控制器作为许多滚动视图的代表。我宁愿通过委托来解决它。
The answer above all did not quite work our for me, since I run into a cyclic call of
scrollViewDidScroll
. This happend, because setting the content offset of a scroll view also callsscrollViewDidScoll
. I solved it by putting a lock between it, which is set based on if a scroll view is being dragged by the user or not, so the syncing won't happen by setting the content offset:This code can be refactored based on how many scroll views are used and based on who owns them. I won't recommend having one controller being the delegate of many scroll views. I would rather solve it with delegation.