如何使collectionView单元格的分页动画滚动到中心?

时间:2017-08-22 03:09:06

标签: ios swift

我正在使用swift 3来编写一个UIViewController的应用程序,如下图所示。它在顶部包含一个水平滚动collectionView(蓝色块),其功能是在不同的标签之间切换(第一个,上一个,当前,下一个,最后一个......等等,标签总数是没有固定)。我需要实现的是,在滚动(或平移)集合视图时,'NEXT''PREV'应该移动(并自动锚定)到中心速度类似于分页动画。我怎么能实现这个目标?目前我使用Paging Enabled的{​​{1}}属性,但这只适用于窗口中有一个标签的情况。

类似的功能可能看起来像iTunes应用程序的中间“专辑”部分,一旦检测到任何滑动/平移手势,collectionView单元将自动滚动到某个预定义的点,并带有一些动画。

enter image description here

2 个答案:

答案 0 :(得分:1)

根据你的评论,如果你想点击选择,你需要做两件事

1-在viewDidLoad中禁用集合视图滚动

collectionView.isScrollingEnabled = false 

2-在中心显示所选单元格,将其添加到didSelectItemAtIndexPath方法

 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

collection.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizantally)

let cell  = collectionView.cellForItem(at : indexPath) as! YourCollectionViewCellClass
cell.titleLable.font = UIFont.boldSystemFont(ofSize : 20)
}

答案 1 :(得分:0)

感谢Raheel的回答here,我终于找到了一种理想的滚动效果。一些关键功能在swift中列出如下:

  1. 首先,停用Paging Enabled
  2. scrollView属性
  3. 定义setIdentityLayout()setNonIdentityLayout(),它定义了所选/未选定单元格的布局(例如,在这种情况下为MyCollectionViewCell

  4. 定义一些相关属性,例如:

    lazy var COLLECTION_VIEW_WIDTH: CGFloat = {
        return CGFloat(self.collectionView.frame.size.width / 2)
    }()
    
    fileprivate let TRANSFORM_CELL_VALUE = CGAffineTransform(scaleX: 1, y: 1) // Or define other transform effects here
    fileprivate let ANIMATION_SPEED = 0.2
    
  5. UIScrollViewDelegate实施以下关键方法:

    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        // Do tableView data refresh according to the corresponding pages here
    }
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    
        // Scroll to corresponding position
        let pageWidth: Float = Float(COLLECTION_VIEW_WIDTH)  // width + space
        let currentOffset: Float = Float(scrollView.contentOffset.x)
        let targetOffset: Float = Float(targetContentOffset.pointee.x)
        var newTargetOffset: Float = 0
    
        if targetOffset > currentOffset {
            newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth
        }
        else {
            newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth
        }
        if newTargetOffset < 0 {
            newTargetOffset = 0
        }
        else if (newTargetOffset > Float(scrollView.contentSize.width)){
            newTargetOffset = Float(Float(scrollView.contentSize.width))
        }
    
        targetContentOffset.pointee.x = CGFloat(currentOffset)
        scrollView.setContentOffset(CGPoint(x: CGFloat(newTargetOffset), y: scrollView.contentOffset.y), animated: true)
    
        // Set transforms
        let identityIndex: Int = Int(newTargetOffset / pageWidth)
    
        var cell = delegate!.roomCollections.cellForItem(at: IndexPath.init(row: identityIndex, section: 0)) as? MyCollectionViewCell
    
        UIView.animate(withDuration: ANIMATION_SPEED, animations: {
            cell?.transform = CGAffineTransform.identity
            cell?.setIdentityLayout()
        })
    
        // right cell
        cell = delegate!.roomCollections.cellForItem(at: IndexPath.init(row: identityIndex + 1, section: 0)) as? MyCollectionViewCell
    
        UIView.animate(withDuration: ANIMATION_SPEED, animations: {
            cell?.transform = self.TRANSFORM_CELL_VALUE
            cell?.setNonIdentityLayout()
        })
    
        // left cell, which is not necessary at index 0
        if (identityIndex != 0) { 
            cell = delegate!.roomCollections.cellForItem(at: IndexPath.init(row: identityIndex - 1, section: 0)) as? MyCollectionViewCell
            UIView.animate(withDuration: ANIMATION_SPEED, animations: {
                cell?.transform = self.TRANSFORM_CELL_VALUE
                cell?.setNonIdentityLayout()
            })
        }
    }
    
  6. 最后,在func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)中定义初始布局:

    if (indexPath.row == 0 && /* other first item selected condition */) {
        cell.setIdentityLayout()
    } else {
        cell.transform = TRANSFORM_CELL_VALUE 
        cell.setNonIdentityLayout()
    }
    
  7. 要添加触摸滚动效果,只需将目标添加到每个集合视图,然后执行类似的计算,更改scrollView的contentOffSet,此处省略,因为此功能更简单而不是主要问题。