让两个UIScrollView跟着彼此滚动

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (171)

我将如何使两个滚动视图跟随彼此滚动?

例如,我在屏幕左侧有一个滚动视图(A),其内容可以上下滚动,但不能左右滚动。滚动视图B与A的向上和向下匹配,但也可以向左和向右滚动。滚动视图A始终在屏幕上。

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

我该如何做到这一点,上下滚动(任一视图)也会使其他视图以相同的上下方向滚动?还是有另一种方法来做到这一点?

提问于
用户回答回答于

将滚动视图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)
    }
用户回答回答于

我在iOS 11上尝试了Simon Lee的回答。它工作但不是很好。两个滚动视图是同步的,但是使用他的方法,滚动视图将失去惯性效果(当它释放手指后继续滚动)和弹跳效果。我认为这是由于设置contentOffsetthrough 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)不会循环调用,并且滚动发生得非常平滑,并具有惯性和弹跳效果,就像单个滚动视图一样。

所属标签

可能回答问题的人

  • Hanzo

    2 粉丝0 提问7 回答
  • Richel

    9 粉丝0 提问4 回答
  • software

    10 粉丝488 提问3 回答
  • 不吃貓的鱼oo

    6 粉丝466 提问2 回答

扫码关注云+社区

领取腾讯云代金券