自定義UICollectionViewFlowLayout實現橫向滾動時,離中心點越近,item越大,離中心店越遠,item越小的效果
阿新 • • 發佈:2021-06-15
控制器程式碼
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.addSubview(collectionView) } lazy var collectionView:UICollectionView = { let layout = Layer() layout.itemSize = CGSize(width: 160, height: 160) layout.scrollDirection = .horizontal let margin = (UIScreen.main.bounds.size.width - 160) * 0.5 layout.sectionInset = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) layout.minimumLineSpacing = 50 let collectionView = UICollectionView(frame: CGRect(x: 0, y: 200, width: UIScreen.main.bounds.size.width, height: 200), collectionViewLayout: layout) collectionView.backgroundColor = .purple collectionView.delegate = self collectionView.dataSource = self collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "reuseId") return collectionView }() }
自定義UICollectionViewFlowLayout
class Layer: UICollectionViewFlowLayout { /** 什麼時候呼叫:collectionView第一次佈局的時候呼叫 還有重新整理的時候呼叫 有什麼作用:計算cell 的佈局 條件:cell 位置固定不變的時候 */ // open override func prepare(){ // super.prepare() // print("呼叫") // } /** UICollectionViewLayoutAttributes 確定cell的尺寸的 一個 UICollectionViewLayoutAttributes 物件對應這一個cell 是要拿到這個類 就相當於拿到cell */ //作用:返回cell 的尺寸 open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?{ // print(rect) //1.獲取當前顯示的區域 let attrs = super.layoutAttributesForElements(in: self.collectionView?.bounds ?? CGRect.zero) // print(attrs) //2.獲取當前顯示的cell 的佈局 // 效果: 越靠近中心點就越大 if let attrs = attrs { for attr in attrs { //2.1求cell 與中心點的距離 let margin = abs((attr.center.x - (self.collectionView?.contentOffset.x ?? 0) - ((self.collectionView?.frame.size.width ?? 0) * 0.5))) //2.2計算比例 let scale = 1 - (margin / ((self.collectionView?.frame.size.width ?? 0) * 0.5) * 0.25) attr.transform = CGAffineTransform(scaleX: scale, y: scale) } } return attrs } /** 在滾動collectionView 的時候是否允許佈局 返回YES 每次都會重新整理佈局 */ override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } /** 什麼時候呼叫: 使用者手指鬆開的時候 作用:確定最終偏移量 */ override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { print("確定偏移量") //最終偏移量 是否等於手指離開的偏移量(不等於) var finalPoint = super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) // print(finalPoint, self.collectionView?.contentOffset) //1. 獲取最終顯示區域 let collectionW = self.collectionView?.frame.size.width ?? 0 let finalRect = CGRect(x: finalPoint.x, y: 0, width: collectionW, height: CGFloat.greatestFiniteMagnitude) //獲取最終顯示cell let attrs = super.layoutAttributesForElements(in: finalRect) if let attrs = attrs { var minDetal = CGFloat.greatestFiniteMagnitude for attr in attrs { var detal = (attr.center.x - (finalPoint.x ?? 0) - ((self.collectionView?.frame.size.width ?? 0) * 0.5)) //獲取中心點的距離 if abs(detal) < abs(minDetal) { minDetal = detal } } finalPoint.x += minDetal } return finalPoint } /** 計算collectionView 的滾動範圍 */ // override var collectionViewContentSize: CGSize{ // return super.collectionViewContentSize // } }