Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

Установите делегат прокрутки в виде 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)
    }

Ответ 2

Я попробовал ответить Саймон Ли на iOS 11. Это сработало, но не очень хорошо. Два вида прокрутки были синхронизированы, но с использованием его метода прокрутки отображали эффект инерции (когда он продолжает прокручиваться после отпускания пальца) и эффект подпрыгивания. Я думаю, это связано с тем, что установка метода contentOffset через 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) не вызывается циклически, и прокрутка происходит очень плавно и с инерционными и прыгающими эффектами, как при одном прокрутке.