Создание двух UIScrollViews сопровождается прокруткой друг друга

17

Как бы я сделал два вида прокрутки, следуя за прокруткой друг друга?

Например, у меня есть вид прокрутки (A) слева от экрана, содержимое которого может перемещаться вверх и вниз, но не влево и вправо. Просмотр прокрутки B соответствует вверх и вниз по A, но также может прокручиваться влево и вправо. Прокрутка A всегда находится на экране.

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

Как мне сделать так, чтобы прокрутка вверх и вниз (любого вида) также прокручивала другую прокрутку в том же направлении вверх-вниз? Или есть другой способ сделать это?

    
задан cannyboy 27.10.2011 в 17:38
источник

2 ответа

40

Установите делегат прокрутки в виде 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)
    }
    
ответ дан Simon Lee 27.10.2011 в 17:54
источник
  • Awesome - это просто спасло мне целую кучу времени ... –  Matt Fellows 27.02.2012 в 17:32
  • Можете ли вы предложить мне прокрутить с разной скоростью –  Sanjeev Rao 14.05.2013 в 14:43
  • Большое спасибо! Это спасло меня так много времени. :) –  nithinreddy 28.01.2016 в 16:21
1

Я попробовал ответить Саймон Ли на iOS 11. Это сработало, но не очень хорошо. Два вида прокрутки были синхронизированы, но с использованием его метода прокрутки отображали эффект инерции (когда он продолжает прокручиваться после отпускания пальца) и эффект подпрыгивания. Я думаю, что это связано с тем, что установка метода contentOffset through setContentOffset(offset, animated: false) вызывает циклические вызовы метода делегата scrollViewDidScroll(_ scrollView: UIScrollView) (см. этот вопрос )

Вот решение, которое работало для меня на iOS 11:

 // 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 с тем, который был прокручен пользователем. Таким образом, метод делегата scrollViewDidScroll(_ scrollView: UIScrollView) не вызывается циклически, и прокрутка происходит очень плавно и с инерционными и прыгающими эффектами, как при одном прокрутке.

    
ответ дан Dmitry Klochkov 30.10.2017 в 10:32
источник
  • Я просто попробовал ваше решение, но scrollBounds всегда одно и то же. вы делаете что-то другое вне кода, который вы предоставляете? –  Jonathanff 05.11.2017 в 04:34
  • Нет. Что касается прокрутки синхронизации двух видов прокрутки, это все, что у меня есть в моем проекте, и оно работает нормально. –  Dmitry Klochkov 05.11.2017 в 14:48