我正在使用swift 3来编写一个UIViewController
的应用程序,如下图所示。它在顶部包含一个水平滚动collectionView
(蓝色块),其功能是在不同的标签之间切换(第一个,上一个,当前,下一个,最后一个......等等,标签总数是没有固定)。我需要实现的是,在滚动(或平移)集合视图时,'NEXT'或'PREV'应该移动(并自动锚定)到中心速度类似于分页动画。我怎么能实现这个目标?目前我使用Paging Enabled
的{{1}}属性,但这只适用于窗口中有一个标签的情况。
类似的功能可能看起来像iTunes应用程序的中间“专辑”部分,一旦检测到任何滑动/平移手势,collectionView单元将自动滚动到某个预定义的点,并带有一些动画。
答案 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中列出如下:
Paging Enabled
scrollView
属性
定义setIdentityLayout()
和setNonIdentityLayout()
,它定义了所选/未选定单元格的布局(例如,在这种情况下为MyCollectionViewCell
)
定义一些相关属性,例如:
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
为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()
})
}
}
最后,在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()
}
要添加触摸滚动效果,只需将目标添加到每个集合视图,然后执行类似的计算,更改scrollView
的contentOffSet,此处省略,因为此功能更简单而不是主要问题。