周末没有加班,闲来无事,就将之前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地址