---恢復內容開始---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來存儲的。