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地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章