UICollectionView在Swift3.0中的用法

UICollectionView在Swift3.0中的用法

UICollectionView的初始化跟OC中是類似的,建立 GameView 集成自 UICollectionView 。注意不一樣於UITableView的用法,他須要用 UICollectionViewFlowLayout 來指定一些須要設置的屬性,或者能夠經過遵照swift

UICollectionViewDelegateFlowLayout 這個代理來實現。下面我用設置屬性的方式來實現的,比較方便。緩存

        //佈局
        layout.scrollDirection = .vertical//滑動方向  這個就是默認是縱向滑動
        layout.itemSize = CGSize(width: width, height: width)//item的size
        layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)//section距上下左右的數據
        layout.minimumLineSpacing = CGFloat(integerLiteral: 5)//若是是縱向滑動的話即行間距,若是是橫向滑動則爲列間距
        layout.minimumInteritemSpacing = CGFloat(integerLiteral: 5)//若是是縱向滑動的話即列間距,若是是橫向滑動則爲行間距
        layout.headerReferenceSize = CGSize(width: maiSrc.width, height: 30)//設置headerView的size
        layout.footerReferenceSize = CGSize(width: maiSrc.width, height: 30)//設置footerView的size

下邊直接貼出整個的源碼 ,調用就異常簡單了 :數據結構

   override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = UIColor.white()
        
        let game = GameView.init(frame: CGRect(x: 0, y: 20, width: maiSrc.width, height: maiSrc.height - 20))
        self.view.addSubview(game)
        
        
    }

 

 源碼 :app

//
//  GameView.swift
//  CharacterGame
//
//  Created by 江南花印孓 on 2016/6/28.
//  Copyright © 2016年 恆江. All rights reserved.
//

import UIKit

let identifier = "identifier"
let headerIdentifier = "headerIdentifier"
let footerIdentifier = "footerIdentifier"

class GameView: UICollectionView ,UICollectionViewDelegate ,UICollectionViewDataSource ,UICollectionViewDataSourcePrefetching{
    
    internal var num = 6
    internal var items = 196
    var source = [Int]()
    
    //MARK:---------這裏是一個 init 初始化標記
    init(frame:CGRect) {
        //TODO: -----int 初始化方法 裏邊要作的事情----
        let layout = UICollectionViewFlowLayout.init()//經過Layout的一些屬性把對應數據設置好,則不用再實現對應函數
        let leftWidth = maiSrc.width - CGFloat(integerLiteral: ( num + 1 ) * 5)
        let width = leftWidth / CGFloat(integerLiteral: num)
        for i in 1...items {
            source.append(i)
        }
        //FIXME: 問題一 :  除了使用layout屬性設置還能夠用什麼方法來實現?
        //佈局
        layout.scrollDirection = .vertical//滑動方向  這個就是默認是縱向滑動
        layout.itemSize = CGSize(width: width, height: width)//item的size
        layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)//section距上下左右的數據
        layout.minimumLineSpacing = CGFloat(integerLiteral: 5)//若是是縱向滑動的話即行間距,若是是橫向滑動則爲列間距
        layout.minimumInteritemSpacing = CGFloat(integerLiteral: 5)//若是是縱向滑動的話即列間距,若是是橫向滑動則爲行間距
        layout.headerReferenceSize = CGSize(width: maiSrc.width, height: 30)//設置headerView的size
        layout.footerReferenceSize = CGSize(width: maiSrc.width, height: 30)//設置footerView的size
        
        //FIXME: 注意這個父類 init 方法寫在這裏了
        super.init(frame: frame, collectionViewLayout: layout)
        
        //初始化
        self.backgroundColor = UIColor.white()
        self.delegate = self
        self.dataSource = self
        self.prefetchDataSource = self;//這個協議對應 UICollectionViewDataSourcePrefetching 是 10.0 之後新加的兩個方法,下面介紹
        self.isPrefetchingEnabled = true//容許實現 UICollectionViewDataSourcePrefetching 這個協議 10.0 後新加的
        self.allowsMultipleSelection = true//容許多選
        self.showsVerticalScrollIndicator = false //右側那條上下滑動的線
        
        //這三個方法能夠看底層說明,講的很詳細
        self.register(singleCell.self, forCellWithReuseIdentifier: identifier)
        self.register(headerView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerIdentifier)
        self.register(footerView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: footerIdentifier)
        
        //FIXME: 一個很實用的系統定義宏 , 用來打印對應object的全部屬性信息
        dump(self)

        /*
         *  重排手勢 UICollectionViewController 裏有一個默認爲 true 的屬性用來設置開啓重排手勢功能,實現對應的代理函數便可實現對應功能。
         *  collectionView(_ : , moveItemAt : , to : )
         *  這裏集成自 UICollectionView ,沒有手勢,因此須要添加一個 長按手勢 。
         */
        let longGesture = UILongPressGestureRecognizer.init(target: self, action: #selector(handlelongGesture))
        self.addGestureRecognizer(longGesture)
    }
    
   //MARK: ---------------     my  action       ------------
    func handlelongGesture(longGesture:UILongPressGestureRecognizer) -> Void {
        switch longGesture.state {
        case .began:
            //判斷手勢落點所在 item 的 indexPath 是否在 collectionView 內
            let index = self.indexPathForItem(at: longGesture.location(in: self))
            if index == nil {
                break
            }
            //若是在,那麼就開始移動這個位置上的cell
            self.beginInteractiveMovementForItem(at: index!)
            break
        case .changed:
            //當位置發生偏移時調用該函數,判斷新的位置是否在 collectionView 之內來決定是放回原位置仍是移動到新的位置
            self.updateInteractiveMovementTargetPosition(longGesture.location(in: self))
            print("on the way")
            break
        case .ended:
            /*
             *  接受後調用下邊兩個函數中的一個通知 collectionView 軌跡交互移動已經結束,把item永久的移動到新位置,同時響應
             *  collectionView(_ : , moveItemAt : , to : ) 函數  來處理數據源  確保數據源的數據結構沒問題
             */
            self.endInteractiveMovement()
            break
        default:
            self.cancelInteractiveMovement()
            break
        }
    }
    
    //MARK: --------       UICollection View Delegate      -------
    func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
        return true
    }
    
    /*  注意:cell重置須要在 UICollectionViewController 裏開啓一個手勢 installsStandardGestureForInteractiveMovement 開關
     *  以後由控制器給 collectionView 添加長按手勢 LongPressGesture 以後纔會走下邊的函數
     *  單純的 collectionView 並無這個手勢,因此沒法觸發這個代理
     */
    func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let str = source[sourceIndexPath.item!]
        source.remove(at: sourceIndexPath.item!)
        source.insert(str, at: destinationIndexPath.item!)
        print("this is a test String")
    }
    
    
    override func numberOfSections() -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! singleCell
        let index = source[indexPath.item!]
        cell.age.text = String.init(index)
        cell.backgroundColor = UIColor.red()
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        
        /**
         *   注意要點
         *   1.supplementaryView 的返回類型爲 UICollectionReusableView ,不能混淆,Swift裏邊對於返回值的類型要去很嚴格。
         *   2.UICollectionReusableView 繼承自 UIView ,是 UIView 的子類
         *   3.kind 分爲 footer 和 header 兩種,區分開來
         *   4.kind 和 identifier 要對應起來,由於是兩個不一樣的 reuse identifier
         */
        if kind == UICollectionElementKindSectionHeader {
            let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as! headerView
            header.name.text = "測試"
            
            return header
        }
        let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerIdentifier, for: indexPath)
        return footer
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let index = indexPath.item! as Int
        print("\(index)")
    }
    
    //MARK: -----------  UICollectionViewDataSourcePrefetching  預取  緩存 -----
    /*  獲取 ‘預取’ 地址集合  item出現以前的預處理,iOS 10.0之後新加的,不明覺厲。。不知道有什麼用
     *  目前來看 只能是單純的提高運行效率   作一下預處理。。。
     *  當界面顯示不完 item 時 , 相似複用隊列同樣能夠緩存一部分還沒有顯示出來的 item ,具體緩存多少目前還沒搞清楚,
     *  貌似跟幾何面積有關,單個item越大,緩存的行數越少;相反,item的size越小,緩存的行數越多
     */
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        //dump(indexPaths)
    }
    /*
     *  optional public func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath])
     *  這個函數的做用看文檔說明,我的理解爲 已經緩存,事實上卻又沒有用到,就是沒有顯示的 item 的子集。
     */
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class headerView: UICollectionReusableView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.addSubview(name)
        //單純的個體案例   用不到三方框架   用 VFL 適配
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[name]-0-|",
                                                           options: [],
                                                           metrics: nil,
                                                           views: ["name":name]))
        
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[name]-0-|",
                                                           options: [],
                                                           metrics: nil,
                                                           views: ["name" : name ]))
        self.backgroundColor = UIColor.orange()
    }
    
    //懶加載
    lazy var name: UILabel = {
        let name = UILabel.init()//2098
        name.translatesAutoresizingMaskIntoConstraints = false
        name.backgroundColor = UIColor.red()//
        name.textAlignment = .center
        name.textColor = UIColor.white()
        return name
    }()
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class footerView: UICollectionReusableView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.backgroundColor = UIColor.green()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
class singleCell: UICollectionViewCell {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(age)
        
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat:  "H:|-[age]-|",
                                                           options: [],
                                                           metrics: nil,
                                                           views: ["age":age]))
        
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[age]-|",
                                                           options: [],
                                                           metrics: nil,
                                                           views: ["age" : age ]))
    }
    
    lazy var age: UILabel = {
        let age = UILabel.init()
        age.translatesAutoresizingMaskIntoConstraints = false
        age.backgroundColor = UIColor.blue()
        age.textAlignment = .center
        age.textColor = UIColor.white()
        age.text = "0"
        return age
    }()
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
相關文章
相關標籤/搜索