UICollectionView 實現,自動滾動、一屏橫向顯示3個view

前言

實現UICollectionView的自動滾動,以及一屏下,中間顯示一個view,兩邊顯示半個view的效果,
如圖:git

圖片描述

自動滾動實現邏輯

自動滾動是使用Timer實現,每一個一段時間讓UICollectionView自動滾動下便可。github

  • 定義一個Timer
//自動滾動計時器
var autoScrollTimer:Timer?
  • 定義一個下標,記錄UICollectionView的下標
var index: Int = 0
  • 啓動一個定時器
func startTimer() {
        //設置一個定時器,每三秒鐘滾動一次
        autoScrollTimer = Timer.scheduledTimer(timeInterval: 3, target: self,
                                               selector: #selector(UICollectionViewTypeOneController.scroll),
                                               userInfo: nil, repeats: true)
    }
定時器沒3秒響應scroll方法一次
  • 自動滾動
//計時器時間一到,滾動一張圖片
    @objc func scroll(){
        index = index + 1
        index = index >= dataCollection.count ? 0 : index
        collectionView.scrollToItem(at: IndexPath.init(row: index, section: 0), at: .centeredHorizontally, animated: true)
    }
index 是下標,因此當index和數據源的大小一致時,就把index重置爲0,不然就加一,scrollToItem方法是UICollectionView的自帶方法,實現滾動效果。

一屏顯示三個View

核心思想是實現UICollectionViewFlowLayout的prepare()和targetContentOffset方法
  • 建立一個類實現UICollectionViewFlowLayout
class ProductAHorCollectionViewFlowLayout: UICollectionViewFlowLayout {
    override func prepare() {
        super.prepare()
        }
        override func targetContentOffset(forProposedContentOffset
            proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        }
}
  • prepare方法

prepare方法咱們作一些初始化操做,如設置Item的大小和左右邊距等ide

let left = (self.collectionView!.bounds.width - itemWidth) / 2
 let top = (self.collectionView!.bounds.height - itemHeight) / 2
 self.sectionInset = UIEdgeInsetsMake(top, left, top, left)
left 保證第一個和最後一個ItemView會居中顯示
top 保證只顯示一行。

至此咱們已經實現了一個view居中顯示,兩邊顯示個頭的效果,可是由於咱們要保證,用戶滑動結束後,中間的view一直顯示在中間,因此要實現下targetContentOffset方法。spa

  • targetContentOffset方法
override func targetContentOffset(forProposedContentOffset
        proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        //中止滾動時的可見區域
        let lastRect = CGRect(x: proposedContentOffset.x, y: proposedContentOffset.y,
                              width: self.collectionView!.bounds.width,
                              height: self.collectionView!.bounds.height)
        //當前屏幕中點,相對於collect view上的x座標
        let centerX = proposedContentOffset.x + self.collectionView!.bounds.width * 0.5;
        //這個可見區域內全部的單元格屬性
        let array = self.layoutAttributesForElements(in: lastRect)
        
        //須要移動的距離
        var adjustOffsetX = CGFloat(MAXFLOAT);
        for attri in array! {
            //每一個單元格里中點的偏移量
            let deviation = attri.center.x - centerX
            //保存偏移最小的那個
            if abs(deviation) < abs(adjustOffsetX) {
                adjustOffsetX = deviation
            }
        }
        //經過偏移量返回最終停留的位置
        return CGPoint(x: proposedContentOffset.x + adjustOffsetX, y: proposedContentOffset.y)
    }
原理就是計算出每個view 的偏移量,得到最小偏移量的那個,本來停留的的位置 + 最小偏移量,就是一個view的居中位置。

Git:https://github.com/LSnumber1/...code

相關文章
相關標籤/搜索