週末沒有加班,閒來無事,就將之前Object-C寫的代碼功能塊改爲swift,項目重構時將會用到,改完測試後現在將代碼貼出來做一個記錄,接下來的時間都會是在項目重構上,leader讓項目重構改爲swift的,
1.圖片加載是Kingfisher第三方
2.基於MVC設計模式
設計思路
1.創建繼承自UICollectionViewFlowLayout的類,重寫系統方法,
2.加載layout的時候這個方法override func prepare() {}調用
3.在這override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {}方法中將決定每一個item的佈局位置,
4.這個方法override var collectionViewContentSize: CGSize{}設置item的大小(和oc寫法有很大的區別)
詳細的代碼我上傳到了github上 詳細代碼github地址
/// 初始化
override func prepare() {
super.prepare()
contentHeight = 0
//清除之前計算的高度
self.columnHeights.removeAllObjects()
for _ in 0..<columCount() {
columnHeights.add(edgeInsets().top)
}
//清除之前所有的佈局
self.attrsArray.removeAllObjects()
///創建每一個cell對應的佈局屬性
let count:NSInteger = (collectionView?.numberOfItems(inSection: 0))!
for i in 0..<count {
//創建位置
let indexpath:NSIndexPath = NSIndexPath(item: i, section: 0)
//獲取indexpath位置cell對應的佈局屬性
let atts:UICollectionViewLayoutAttributes = layoutAttributesForItem(at: indexpath as IndexPath)!
attrsArray.add(atts)
}
}
//決定cell的排布位置
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return (attrsArray as! [UICollectionViewLayoutAttributes])
}
//返回indexpath位置cell對應的佈局屬性
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
//創建佈局屬性
let attributes:UICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
//collectionview的寬度
let collectionViewW = collectionView?.frame.size.width
//設置佈局屬性的frame
let w:CGFloat = (collectionViewW! - edgeInsets().left - edgeInsets().right - CGFloat((columCount() - 1))*self.columnMargin())/CGFloat(self.columCount())
let h:CGFloat = (delegate?.waterflowLayout(waterflowLayout: self, heightForItemIndex: indexPath.item, itemWidth: w))!
//找出最短的那一列
var desColumn = 0;
var minColumnHeight:CGFloat = self.columnHeights[0] as! CGFloat
for i in 0..<columCount() {
//取第i列的高度
let columnHeigh:CGFloat = self.columnHeights[i] as! CGFloat
if minColumnHeight > columnHeigh {
minColumnHeight = columnHeigh
desColumn = i
}
}
let x:CGFloat = self.edgeInsets().left + CGFloat(desColumn) * (w + columnMargin())
var y:CGFloat = minColumnHeight;
if y != edgeInsets().top{
y += Rowmargin()
}
attributes.frame = CGRect(x: x, y: y, width: w, height: h)
//跟新最短的那列的高度
columnHeights[desColumn] = (attributes.frame.maxY)
//記錄內容的高度
let columnheight:CGFloat = columnHeights[desColumn] as! CGFloat
if self.contentHeight! < columnheight {
self.contentHeight = columnheight
}
return attributes
}
override var collectionViewContentSize: CGSize{
get{
return CGSize(width: 0, height: self.contentHeight! + self.edgeInsets().bottom)
}
}
最後來看一下具體怎麼使用
lazy var CollectionView:UICollectionView = {
let layout:cqWaterFlowLayout = cqWaterFlowLayout() //初始化自定義的layout,
layout.delegate = self //這個代理必須寫,因爲計算高度的代理需要使用
let collection = UICollectionView(frame:CGRect(x: 0, y: 0, width:view.frame.size.width, height:view.frame.size.height), collectionViewLayout: layout)
collection.backgroundColor = UIColor.white
collection.register(UINib.init(nibName: "ShopsCell", bundle: nil), forCellWithReuseIdentifier: "shops")
collection.dataSource = self
return collection;
}()
extension ViewController:UICollectionViewDataSource,cqWaterFlowLayoutDelegate,UITableViewDelegate{
//返回的是item的高度
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return shopsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:ShopsCell = CollectionView.dequeueReusableCell(withReuseIdentifier: "shops", for: indexPath) as! ShopsCell
let model:Source = shopsArray[indexPath.row] as! Source
cell.setShopsData(shop: model)
return cell
}
///item列數
func columnCountInWaterflowLayout(waterflowLayout: cqWaterFlowLayout) -> CGFloat {
return 3
}
func waterflowLayout(waterflowLayout: cqWaterFlowLayout, heightForItemIndex: NSInteger, itemWidth: CGFloat) -> CGFloat {
let model:Source = shopsArray[heightForItemIndex] as! Source
return itemWidth * model.h! / model.w!
}
///item左右間距
func columnMarginInWaterflowLayout(waterflowLayout: cqWaterFlowLayout) -> CGFloat {
return 5
}
///item上下的間距
func rowMarginInWaterflowLayout(waterflowLayout: cqWaterFlowLayout) -> CGFloat {
return 10;
}
///layout距離邊框的距離
func edgeInsetsInWaterflowLayout(waterflowLayout: cqWaterFlowLayout) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 10, 10, 10)
}
}
詳細的代碼我上傳到了github上 詳細代碼github地址