缩放和滚动支持UICollectionView

时间:2018-11-26 12:25:46

标签: ios objective-c uiscrollview uicollectionview

我需要支持UICollectionView中的缩放。

要求:

  1. 放大后,它必须支持通过水平和垂直滚动查看UICollectionViewCell的隐藏区域(视口之外的区域)。
  2. 缩小/放大后,它必须支持UICollectionViewCell的选择并能够滚动UICollectionView(基本上是默认的UICollectionView行为,即返回无缩放状态时。)。

尝试的方法列表:

  1. 添加了GestureRecognizer

a。添加了UIPinchGestureRecognizer以按比例转换UICollectionView。 b。放大后,无法移动UICollectionViewcell来查看隐藏区域。 C。添加了UIPanGestureRecognizer来移动UICollectionView的中心 d。移动UICollectionView效果很好。 e。现在,我们无法选择UICollectionViewCell,也无法滚动UICollectionView。

  1. 在UIScrollView内添加了UICollectionView

a。添加了带有委托的UIScrollView。 b。添加了UICollectionView作为UIScrollView的子视图 C。由于UICollectionView(由UIScrollView继承)消耗了缩放手势,因此无法进行缩小

  1. 将UIColectionView和UIScrollView都添加为兄弟

a。向父级添加了UIScrollView和UICollectionView。 b。将UIScrollView放在前面。 C。缩放有效,但无法平移以查看隐藏区域。

请建议是否有任何方法可以解决上述问题,或者提出一种更好的策略来实现collectionView的缩放。

1 个答案:

答案 0 :(得分:0)

我已经使用UIScrollView和UICollectionViewLayout子类解决了这个问题。

1)将UIScrollView放在具有相同框架的UICollectionView顶部。

 self.view.addSubview(scrollView)
 scrollView.addSubview(dummyViewForZooming)
 scrollView.frame = collectionView.frame
 scrollView.bouncesZoom = false
 scrollView.minimumZoomScale = 0.5
 scrollView.maximumZoomScale = 3.0

2)将UIScrollView和zoomingView的contentSize设置为与UICollectionView相同

  override func viewDidLayoutSubviews() {
    super.viewWillLayoutSubviews()

    scrollView.contentSize = layout.collectionViewContentSize
    dummyViewForZooming.frame = CGRect(origin: .zero, size: layout.collectionViewContentSize)
    scrollView.frame = collectionView.frame
  }

3)从UICollectionView中删除所有手势识别器,并为UIScrollView添加一个委托。将轻击手势识别器添加到UIScrollview

    collectionView.gestureRecognizers?.forEach {

        collectionView.removeGestureRecognizer($0)

    }
    let tap = UITapGestureRecognizer.init(target: self, action: #selector(scrollViewWasTapped(sender:)))
    tap.numberOfTapsRequired = 1
    scrollView.addGestureRecognizer(tap)


    scrollView.delegate = self

4)当ScrollView滚动或缩放时,将UICollectionView的contentOffset设置为与ScrollView contentOffset相同,将UICollectionViewLayout的layoutScale设置为zoomscale并使布局无效。

func scrollViewDidZoom(_ scrollView: UIScrollView) {

    if let layout = self.layout, layout.getScale() != scrollView.zoomScale {
        layout.layoutScale = scrollView.zoomScale
        self.layout.invalidateLayout()
        collectionView.contentOffset = scrollView.contentOffset
    }
}

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return dummyViewForZooming
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    collectionView.contentOffset = scrollView.contentOffset

}

5)覆盖UICollectionViewLayout中的prepare方法,浏览所有layoutAttributes并设置一个转换:

    attribute.transformedFrame = attribute.originalFrame.scale(layoutScale)
    let ts = CGAffineTransform(scaleX: layoutScale, y: layoutScale)
        attribute.transform = ts

    let xDifference = attribute.frame.origin.x - attribute.transformedFrame.origin.x
    let yDifference = attribute.frame.origin.y - attribute.transformedFrame.origin.y

    let t1 = CGAffineTransform(translationX: -xDifference, y: -yDifference)
    let t = ts.concatenating(t1)
        attribute.transform = t

6)确保您缩放collectionView内容的大小:

override var collectionViewContentSize: CGSize  {
        return CGSize(width: width * layoutScale, height: height * layoutScale)
    } 

7)从轻击手势识别器拦截轻击并将视图中的位置转换为集合视图中的某个点,然后可以使用indexPathForItem(point :)获取该单元格的indexPath并选择该单元格或将事件传递给单元格的基础视图等。

希望这会有所帮助