Синхронизация позиции прокрутки нескольких экземпляров UITableView - PullRequest
3 голосов
/ 27 марта 2012

У меня есть проект, в котором мне нужно отобразить несколько экземпляров UITableView внутри одного и того же представления на iPad.Они также могут быть повернуты, но я уверен, что это не имеет значения.Пользователь должен не знать, что представление состоит из нескольких табличных представлений.Поэтому я хотел бы сделать так, чтобы при прокрутке одного вида таблицы другие прокручивались одновременно с ним.

Поскольку UITableView является подклассом UIScrollView, я решил, что справлюсьUIScrollViewDelegate методов и передайте их всем табличным представлениям.К сожалению, хотя я могу записывать некоторые события, степень детализации вызова метода недостаточно хороша, и у меня возникают проблемы при передаче этих сообщений в другие представления таблиц.Самое близкое, что я могу получить, это реализовать -scrollViewDidScroll:, а затем вызвать -setContentOffset:animated для каждого табличного представления.Если я пытаюсь отправить это сообщение для всех возможных случаев, я в конечном итоге блокирую, потому что -scrollViewDidScroll получает вызов для моих -setContentOffset:animated вызовов, поэтому я в конечном итоге зависаю.В любом случае, если я устраню блокировку, используя только этот метод для обнаружения прокрутки в одном табличном представлении и затем передавая ее в другие табличные представления, я обнаружу, что, хотя другие табличные представления в конечном итоге прокручиваются в то же место, они отстают на секунду илидва.

Вот пример проекта, который я создал.

Как реализовать это поведение без создания подкласса UITableView?

Ответы [ 3 ]

11 голосов
/ 27 марта 2012

Вы можете обойти проблему гранулярности обратного вызова, наблюдая contentOffset напрямую.В viewDidLoad установите KVO для каждого из представлений таблицы, которые необходимо синхронизировать:

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

Затем, когда вы наблюдаете изменения, временно отцепите наблюдение, обновите смещения других представлений таблицы и повернитенаблюдение снова включено.

- (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];
}

Это, вероятно, можно сделать красивее, но это помогает понять идею.

7 голосов
/ 27 марта 2012

Используйте свойство contentOffset напрямую вместо setContentOffset:animated, чтобы избежать отставания. В вашем примере измените строки 73 и 74 на

self.tableViewMiddle.contentOffset = scrollView.contentOffset;
self.tableViewBottom.contentOffset = scrollView.contentOffset;
2 голосов
/ 16 февраля 2016

Старый вопрос, но вот более простой способ.

  1. Отметьте себя как UITableViewDelegate:

    class MultiTableViewController: UIViewController, UITableViewDelegate { ... }
    
  2. Установите себя в качестве делегата наТабличные представления:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        leftTableView.delegate = self
        rightTableView.delegate = self
    }
    

    (вы также можете выполнить этот шаг в конструкторе интерфейсов).

  3. Реализуйте этот метод:

    func scrollViewDidScroll(scrollView: UIScrollView) {
        leftTableView.contentOffset = scrollView.contentOffset
        rightTableView.contentOffset = scrollView.contentOffset
    }
    

Готово.

Табличное представление имеет представление прокрутки, а протокол UITableViewDelegate содержит все методы UIScrollViewDelegate, так что вы можете просто использовать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...