同时滚动和捏合多个 UiScrollView

Posted

技术标签:

【中文标题】同时滚动和捏合多个 UiScrollView【英文标题】:scroll and pinch in multiple UiScrollViews at the same time 【发布时间】:2017-08-18 15:08:32 【问题描述】:

我有一个带有四个自定义单元格的 UICollectionView。单元格的委托是我的主视图,其中包含 collectionView 并扩展了自定义单元格委托。每个单元格都包含一个UIScrollView,而UIScrollView 又包含并显示一个UIImageView。现在,我可以通过捏合和双击来放大和缩小并在单元格的滚动视图中移动图像。

我的应用程序中有一个“锁定视图”按钮,它应该将视图锁定在一起,这样如果我在一个单元格中捏(缩放或移动),该更改应该被“复制”到其他单元格中。一个单元格中 10% 的缩放增加应该会触发所有其他单元格的 10% 缩放增加(独立于每个单元格电流 zoomScale)。同样,一个单元格向左移动 10 个单位应该将其他单元格向左移动 10 个单位。

我正在使用scrollViewDidScroll(_ scrollView: UIScrollView) 方法来检测我的滚动视图中的变化并调用我的委托,这反过来又可以访问我主要的UICollectionView 中的其他单元格

我的第一个问题是,当我使用UIScrollView.zoom(to : rect)UIScrollView.zoomScale 时,它会在其他单元格中再次触发scrollViewDidScroll(_ scrollView: UIScrollView),从而创建一些无限循环之王,但我设法通过使用来解决这个问题:

var isZooming = false

func scrollViewCustomZoom(to rect: CGRect, animated : Bool ) 
        isZooming = true
        scrollView.zoom(to: rect, animated: animated)
        isZooming = false
    

还有:

func scrollViewDidScroll(_ scrollView: UIScrollView) 
        if isZooming  return 
        // do stuff, typically call the delegate
    

但现在我的问题是:我需要在我的 scrollViewDidScroll 方法中计算什么,以及我需要在委托的每个单元格中设置什么才能获得我正在寻找的行为?

我已经尝试过使用scrollView.boundsscrollView.originscrollView.size,但无法使缩放因子正常运行。

任何帮助都将受到欢迎和赞赏。

【问题讨论】:

【参考方案1】:

找到了我自己的问题的解决方案。此解决方案不会在其他单元格中调用 scrollViewDidScroll(),这正是我想要的。

这是诀窍:

// pinch-pan detection :
func scrollViewDidScroll(_ scrollView: UIScrollView) 
    let newOrigin = scrollView.bounds.origin
    let dx = newOrigin.x - currentScrollViewOrigin.x
    let dy = newOrigin.y - currentScrollViewOrigin.y

    let newScale = scrollView.zoomScale
    let ds = newScale - currentZoomScale

    if let d = delegate
        d.notifyMouvementInCell(self, dx: dx, dy: dy, ds: ds)
    

    currentScrollViewOrigin = scrollView.bounds.origin
    currentZoomScale = scrollView.zoomScale

在我的委托中:

func notifyMouvementInCell(_ cell: customCell, dx: CGFloat, dy: CGFloat, ds: CGFloat)
    if areViewsLocked
        for visibleCell in collectionView.visibleCells as! [IMECasesMultiDisplayCollectionViewCell]
            if visibleCell == cell  continue 
            visibleCell.copyMouvementInForeignCell(horOffset: dx, vertOffset: dy, scaleOffset: ds)
        
    

然后回到我的牢房:

func copyMouvementInForeignCell(horOffset dx: CGFloat, vertOffset dy: CGFloat, scaleOffset ds: CGFloat)
    var newOrigin = scrollView.bounds.origin
    newOrigin.x += dx
    newOrigin.y += dy
    scrollView.bounds.origin = newOrigin

    var newScale = scrollView.zoomScale
    newScale += ds
    let affineTrans = CGAffineTransform(a: newScale, b: 0, c: 0, d: newScale, tx: 0, ty: 0)
    // imageView is the view contained in each of my cell's scrollViews
    imageView.layer.setAffineTransform(affineTrans)

    currentZoomScale = scrollView.zoomScale
    currentScrollViewOrigin = scrollView.bounds.origin

希望有一天这会对某人有所帮助!

【讨论】:

以上是关于同时滚动和捏合多个 UiScrollView的主要内容,如果未能解决你的问题,请参考以下文章

颤动,滚动,捏合和缩放大图像

为捏合手势设置 UIScrollView 的原点

同时检测捏合和旋转手势

同时捏合、拖动和平移

快速捏合缩放

快速捏合和缩放