iOS:如何同步两个 UIScrollview

Posted

技术标签:

【中文标题】iOS:如何同步两个 UIScrollview【英文标题】:iOS: How sync two UIScrollview 【发布时间】:2015-05-22 13:44:06 【问题描述】:

我有两个水平的UIScrollviews。当用户在其中任何一个中拖动手指时,我想同步他们的滚动。这是我的代码:

self.topScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.topScrollView.delegate = self;
self.topScrollView.bounces = YES;

self.bottomScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.bottomScrollView.delegate = self;
self.bottomScrollView.bounces = YES;
...

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

    if (scrollView == self.topScrollView)
    
        self.bottomScrollView.delegate = nil;
    
    else
    
        self.topScrollView.delegate = nil;
    
    ...


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
   
    ...
    self.topScrollView.delegate = self;
    self.bottomScrollView.delegate = self;


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

    ...
    self.topScrollView.delegate = self;
    self.bottomScrollView.delegate = self;


- (void)scrollViewDidScroll:(UIScrollView *)scrollView

    // Sync the two scroll views
    if (scrollView == self.topScrollView)
    
        [self.bottomScrollView setContentOffset:scrollView.contentOffset animated:NO];
    
    else
    
        [self.topScrollView setContentOffset:scrollView.contentOffset animated:NO];
    
    ...

两个滚动视图确实同步滚动,但是问题是所有的弹跳和减速都消失了。整个滚动运动变得非常僵硬。如果我删除所有同步代码,那么每个滚动视图都可以单独工作。 那么,问题是什么?或者UIScrollView可以不同步吗?

【问题讨论】:

【参考方案1】:

您可以使用topScrollView.panGestureRecognizerbottomScrollView.panGestureRecognizer 来获取两个手势识别器并将它们添加到包含两个滚动视图的公共超级视图中。然后,两个孩子都可以识别此超级视图上的平移手势。

您很可能还需要成为两个识别器的代表并让它们同时被识别:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
    return YES;

【讨论】:

我尝试将我的控制器添加为委托,但分配因以下异常而崩溃:'"UIScrollView 的内置平移手势识别器必须将其滚动视图作为其委托" 我想我总是可以继承滚动视图并覆盖该方法。很酷,我认为这应该可行。【参考方案2】:

我根据 jszumski 的回答制定了解决方案。但是,我的情况是两个并排的垂直 UIScrollView(scrollViewLeft 和 scrollViewRight)。它应该适用于水平 UIScrollViews 而无需太多修改。

首先,创建一个自定义 UIScrollView。

//.h file

@interface CSScrollView : UIScrollView

@end

//.m file

@implementation CSScrollView


-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

    return YES;



@end

其次,在你的主视图中,

- (void)viewDidLoad 

    [super viewDidLoad];


    [self.view addGestureRecognizer:self.scrollViewLeft.panGestureRecognizer];

    [self.view addGestureRecognizer:self.scrollViewRight.panGestureRecognizer];


这就是我设置两个同步滚动视图所需的一切。实际效果比在scrollview的scrollViewDidScroll中发送/订阅通知和同步contentOffset的常规方式要好很多。

【讨论】:

【参考方案3】:

@jszumski 用 Swift 回答

    创建 UIScrollView 的自定义子类 符合UIGestureRecognizer委托 覆盖gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)GestureRecognizerDelegate方法
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        return true
    
    两个集合视图需要具有相同的超级视图。将两个手势识别器添加到您的超级视图中
yourSuperview.addGestureRecognizer(scrollView1.panGestureRecognizer)
yourSuperview.addGestureRecognizer(scrollView1)

希望这会有所帮助!

【讨论】:

嗯,如果其中一个滚动视图的内容大小是动态的呢?

以上是关于iOS:如何同步两个 UIScrollview的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中通过 Multipeer Connectivity 临时同步两个 iOS 设备

在 iOS 中同步两个 div 滚动不流畅

ios/macos reminder 与 microsoft todo 同步(提醒事项 微软待办 同步)

IO-同步,异步,阻塞,非阻塞

在 iOS 应用程序之间同步数据有啥好的解决方案? [关闭]

如何同步 URLSession 任务的串行队列?