UICollectionView

---恢復內容開始---swift

(一)使用UITableView進行表格搭建是能夠的。可是UITableView也有本身的侷限性。對於一些更加複雜的佈局,就會不太方便。例如UITableView只能夠縱向排序,每一行只能有一個數組載體cell,不支持一行排列多個。這時候通常會用到UICollectionView。如今app的照片查看,九宮格排布,瀑布流等用的都是UICollectionView。數組

(二)UICollectionView的優點:app

  (1)支持水平和垂直佈局dom

  (2)經過UICollectionViewLayOut類配置的方式進行佈局ide

  (3)相比於TableView的Cell,CollectionView的數據載體Item的大小和位置更加靈活佈局

  (4)經過UICollectionViewLayOutDelegate協議能夠動態的對佈局進行重設spa

  (5)經過獨立的LayOut類來佈局,layOut存放着每一個item的佈局信息,大小,位置,3D變換等。代理

(三)九宮格實現:code

  (1)首先自定義UICollectionView,而且懶加載添加到控制器中blog

 // 懶加載CollectionView
    private lazy var collectionView : SGCollectionView = {
        
       let collectionView = SGCollectionView(frame: CGRectZero, collectionViewLayout: UICollectionViewFlowLayout())
        
        return collectionView
        
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        collectionView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 300)
        
    }

  效果:此時是一個黑色的,沒有通過任何設置的CollectionView

  (2)在自定義的SGCollectionView中進行設置:

    2.1成爲代理,設置layout

    // 注意:這裏面是拿不到item標準的frame的,沒法計算
    private func setupUI() {
    
        backgroundColor = UIColor.whiteColor()
        // 設置代理和數據源
        self.delegate = self
        self.dataSource = self
        
        // 註冊item
        self.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: ITEMID)
    }
    
    // 在這裏設置layout
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 系統的流試佈局
        let layout = collectionViewLayout as! UICollectionViewFlowLayout
        // 橫縱間距
        layout.minimumLineSpacing = margin
        layout.minimumInteritemSpacing = margin
        // 佈局方向,分水平和垂直
        layout.scrollDirection = .Vertical
        let itemWH = CGFloat(Int((self.frame.width - 2 * margin) / 3))
        // 每一個item的尺寸
        layout.itemSize = CGSize(width: itemWH, height: itemWH)
    }

    2.2實現代理

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 9
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        
        let item = collectionView.dequeueReusableCellWithReuseIdentifier(ITEMID, forIndexPath: indexPath)
        
        item.backgroundColor = RandomColor()
        
        return item
    }
  

效果:

此時若是想要讓每一個item顯示別的,例如圖片按鈕云云,只需自定義UICollectionViewCell便可。

(三)建立更加靈活的流試佈局:UICollectionViewDelegateFlowLayout協議中電櫃了不少佈局方法。

UICollectionViewDelegateFlowLayout協議:

public protocol UICollectionViewDelegateFlowLayout : UICollectionViewDelegate {
    
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
}

設置每一個item的尺寸大小:

  // 設置每一個item的大小
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        
        if indexPath.row%2 == 0 {
            return CGSizeMake(50, 50)
        }else {
            return CGSizeMake(100, 100)
        }
        
    }

效果:

(四)自定義UICollectionViewFlowLayout進行參差瀑布流佈局:所謂瀑布流效果,就是分紅兩列或者多列進行數據戰術。每條數據(item)高度也不一樣,造成了良莠不齊的效果。使用原生的UICollectionViewFlowLayout很難作到。這時候咱們只能自定義。

 代碼:

//
//  SGLayout.swift
//  SGCollectionView
//
//  Created by 艾小新 on 16/9/1.
//  Copyright © 2016年 xiaoxin. All rights reserved.
//

import UIKit

class SGLayout: UICollectionViewFlowLayout {
    
    // 佈局多少item
    var itemCount: Int = 0
    
    // 數組保存 每一個item的設置
    var attributeArray: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
    
    
    // 佈局前準備會調用
    override func prepareLayout() {
        
        
        super.prepareLayout()
        
        // 定義2縱向列
        // 計算每個item的寬高
        let width = (UIScreen.mainScreen().bounds.size.width - self.sectionInset.left - self.sectionInset.right - self.minimumInteritemSpacing)/2
        
        var heigh = [self.sectionInset.top,self.sectionInset.bottom]
        
        for i in 0..<itemCount {
            
            // 設置每一個item位置
            let index = NSIndexPath(forItem: i, inSection: 0)
            // 建立佈局
            let attris = UICollectionViewLayoutAttributes(forCellWithIndexPath: index)
            // 隨機高度
            let randH = CGFloat(arc4random()%150 + 40)
            // 那一列高度最小,就放到下面,標記最短的列
            var widL  = 0
            
            if heigh[0] < heigh[1] {
                
                heigh[0] = heigh[0] + randH + self.minimumLineSpacing
                widL = 0
            } else {
                heigh[1] = heigh[1] + randH + self.minimumLineSpacing
                widL = 1
                
            }
            
            // 設置item位置
            attris.frame = CGRectMake(self.sectionInset.left + (self.minimumInteritemSpacing + width) * CGFloat(widL) , heigh[widL] - randH - self.minimumLineSpacing, width, randH)
            
            attributeArray.append(attris)
            
            
          
        }
        if heigh[0] > heigh[1] {
            
            self.itemSize = CGSizeMake(width, heigh[0] - self.sectionInset.top * 2 / CGFloat(itemCount) - self.minimumLineSpacing )
        } else {
            
            self.itemSize = CGSizeMake(width, heigh[1] - self.sectionInset.top * 2 / CGFloat(itemCount) - self.minimumLineSpacing )
        }
        
    }
    
    
    // 這個方法返回佈局數組
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        
        
        return attributeArray
    }
    

}

注意:prepareLayout會調用不少不少次。

效果:

至於瀑布流會另開一篇 單獨分析。

UICollectionView的佈局原理就是用LayOut類對每一個item進行佈局設置,具體配置信息是由UICollectionViewLayOutAttributes來存儲的。

相關文章
相關標籤/搜索