swift自定义流水布局

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值