制作两个UIScrollViews按照彼此滚动

can*_*boy 18 iphone objective-c uiscrollview ios

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

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

-----------------------------------------------------------
|             |                                           |
|             |                                           |
|             |                                           |
|     A       |                    B                      |
|             |                                           |
|    scrolls  |                                           |
|   up & down |              scrolls all directions       |
|             |                                           |
-----------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

我如何制作它以使上下滚动(任一视图)也使另一个视图在相同的上下方向滚动?或者还有另一种方法吗?

Sim*_*Lee 42

将滚动视图A的代理设置为视图控制器...然后...

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  CGPoint offset = scrollViewB.contentOffset;
  offset.y = scrollViewA.contentOffset.y;
  [scrollViewB setContentOffset:offset];
}
Run Code Online (Sandbox Code Playgroud)

如果你想两者互相关注,那么为它们设置委托并使用......

- (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];
  }
}
Run Code Online (Sandbox Code Playgroud)

以上可以重构为具有两个滚动视图并且彼此匹配的方法.

- (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];  
  }
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
Run Code Online (Sandbox Code Playgroud)


Dmi*_*kov 9

我在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
    }
Run Code Online (Sandbox Code Playgroud)

因此,不是设置contentOffset我们使用bounds属性来同步其他scrollView与用户滚动的滚动视图.这种方式scrollViewDidScroll(_ scrollView: UIScrollView)不会循环调用委托方法,并且滚动发生得非常平滑,并且具有惯性和弹跳效果,就像单个滚动视图一样.

  • scrollBounds.origin.x = scrolledView.contentOffset.x ,如果您使用水平滚动视图 (2认同)

Bar*_*nat 7

斯威夫特 5.4 // Xcode 13.1

对我来说完美无缺的工作如下:

  1. 创建 UIScrollView 的自定义子类
  2. 遵守UIGestureRecognizer委托
  3. 重写该gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) GestureRecognizerDelegate方法
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
Run Code Online (Sandbox Code Playgroud)
  1. 两个集合视图需要具有相同的超级视图。将两个手势识别器添加到您的超级视图中
yourSuperview.addGestureRecognizer(scrollView1.panGestureRecognizer)
yourSuperview.addGestureRecognizer(scrollView2.panGestureRecognizer)
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!