同步多个 UITableView 实例的滚动位置 [英] Syncing the scroll position of multiple UITableView instances

查看:25
本文介绍了同步多个 UITableView 实例的滚动位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目,我需要在 iPad 上的同一视图中显示多个 UITableView 实例.它们也恰好是旋转的,但我相当肯定这无关紧要.用户应该不知道视图是由多个表视图组成的.因此,我想让它在我滚动一个 tableview 时,其他的同时滚动.

I have a project in which I need to display multiple UITableView instances inside the same view on the iPad. They also happen to be rotated, but I'm fairly certain this is irrelevant. The user should be unaware that the view is made up of multiple table views. Therefore, I'd like to make it so that when I scroll one tableview, the others scroll with it at the same time.

因为 UITableViewUIScrollView 的子类,我想我可以处理 UIScrollViewDelegate 方法并将它们传递给所有的表视图.不幸的是,虽然我可以捕获一些事件,但方法调用粒度不够精细,并且我无法将这些消息传递给其他表视图.我能得到的最接近的是实现 -scrollViewDidScroll: 然后在每个 tableview 上调用 -setContentOffset:animated .如果我尝试为所有潜在情况发送此消息,我最终会锁定,因为 -scrollViewDidScroll 正在为我的 -setContentOffset:animated 调用调用,所以我最终会冻结向上.无论如何,如果我通过仅使用此方法检测一个 tableview 上的滚动然后将其传递给其他 tableviews 来消除锁定,我发现虽然其他 tableviews 最终滚动到同一位置,但它们滞后一秒或两个.

Because UITableView is a subclass of UIScrollView, I figured I could handle UIScrollViewDelegate methods and pass them along to all of the tableviews. Unfortunately, while I can capture some events, the method call granularity is not fine enough and I'm having trouble passing along these messages to the other tableviews. The closest I can get is implementing -scrollViewDidScroll: and then calling -setContentOffset:animated on every tableview. If I attempt to send this message for all potential cases, I end up locking up because -scrollViewDidScroll is getting called for my -setContentOffset:animated calls, so I end up freezing up. Regardless, if I eliminate the lockup by only using this method to detect scrolling on one tableview and then passing it on to the other tableviews, I find that while the other tableviews do end up scrolling to the same location, They lag behind a second or two.

这是我创建的示例项目.

如何在不继承 UITableView 的情况下实现此行为?

How can I implement this behavior without subclassing UITableView?

推荐答案

直接观察contentOffset可以绕过回调粒度问题.在 viewDidLoad 中,在每个需要同步的表视图上设置 KVO:

You can get around the callback granularity issue by observing contentOffset directly. In viewDidLoad, set up KVO on each of the table views you need to synchronize:

for(UITableView *view in self.tableViewCollection)
{
    [view addObserver:self 
           forKeyPath:@"contentOffset" 
              options:NSKeyValueObservingOptionNew 
              context:NULL];
}

然后,当您观察更改时,暂时取消挂钩,更新其他表视图的偏移量,然后重新打开观察.

Then, when you observe changes, temporarily unhook the observation, update the other table views' offsets, and turn observation back on.

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
{
    static BOOL isObservingContentOffsetChange = NO;
    if([object isKindOfClass:[UITableView class]] 
       && [keyPath isEqualToString:@"contentOffset"])
    {
        if(isObservingContentOffsetChange) return;

        isObservingContentOffsetChange = YES;
        for(UITableView *view in self.tableViewCollection)
        {
            if(view != object)
            {
                CGPoint offset = 
                 [[change valueForKey:NSKeyValueChangeNewKey] CGPointValue];
                view.contentOffset = offset;
            }
        }
        isObservingContentOffsetChange = NO;
        return;
    }

    [super observeValueForKeyPath:keyPath 
                         ofObject:object 
                           change:change 
                          context:context];
}

这可能会变得更漂亮,但它可以传达这个想法.

This can probably be made prettier, but it gets the idea across.

这篇关于同步多个 UITableView 实例的滚动位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆