swift簡單瀑布流的實現_swift

來源:互聯網
上載者:User



1.viewcontroller 設定collectionView布局資訊

import UIKit

import SDWebImage

import MJRefresh

class YFWaterFallViewController:UIViewController,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,YFWaterFallLayoutDelegate {

    let cellID ="waterID"

    var dataLists =Array<YFVideoInfo>()

    var collectionView :UICollectionView!

    let header =MJRefreshNormalHeader()//頂部重新整理

    let footer =MJRefreshAutoNormalFooter()//底部重新整理

    

    overridefunc viewDidLoad() {

        super.viewDidLoad()

        self.view.backgroundColor =UIColor.whiteColor()

        self.navigationItem.title ="瀑布流"

    

        let layout :YFWaterFallCollectionLayout =YFWaterFallCollectionLayout()

        layout.delegate =self

        self.collectionView =UICollectionView(frame:CGRectMake(0,0,screenWidth,screenHeight), collectionViewLayout: layout)

        collectionView.dataSource =self

        collectionView.backgroundColor =UIColor.lightGrayColor()

        collectionView.registerClass(YFWaterFallCollectionViewCell.self, forCellWithReuseIdentifier: cellID)

        header.setRefreshingTarget(self, refreshingAction:#selector(YFWaterFallViewController.headerRefresh))

        collectionView.mj_header =header

        footer.setRefreshingTarget(self, refreshingAction:#selector(YFWaterFallViewController.footerRefresh))

        collectionView.mj_footer =footer

        self.view.addSubview(collectionView)

        self.loadData()

    }

    

    func headerRefresh() {

        self.dataLists = [YFVideoInfo]()

        self.loadData()

    }

    

    func footerRefresh() {

        self.loadData()

    }

    

    //資料載入過程

    func loadData() {

        var params:Dictionary<String,String> = [:]

        params["sign"] =swSign

        YFHttpTool.POST("http://......", parameters: params, success: { (operation, responseObject) in

            YFAlertView.hideHud(self.view)

            if responseObject?.objectForKey("status")as!NSNumber ==1 {

                let tmpArray :NSArray = responseObject!.objectForKey("info")as!NSArray

                for dictin tmpArray {

                    let model :YFVideoInfo =YFVideoInfo.ljbObjectWithDict(dictas!Dictionary)

                    let sizeDict = dict.objectForKey("imgSize")

                    model.w = sizeDict!.objectForKey("width")as?NSNumber

                    model.h = sizeDict!.objectForKey("height")as?NSNumber

                    self.dataLists.append(model)

                }

                self.collectionView.reloadData()

                self.collectionView.mj_header.endRefreshing()

                self.collectionView.mj_footer.endRefreshing()

            } else {

                YFAlertView.showErrorText("查詢失敗!", view: self.view)

            }

            

        }) { (operation, error) in

            print("error:\(error)")

            YFAlertView.hideHud(self.view)

            YFAlertView.showErrorText("網路連接異常!", view: self.view)

        }

    }

    

    //collectionView資料來源設定

    func collectionView(collectionView:UICollectionView, numberOfItemsInSection section:Int) -> Int {

        returnself.dataLists.count

    }

    //給layout高度,根據比例計算

    func collectionView(collectionView:UICollectionView, cellForItemAtIndexPath indexPath:NSIndexPath) -> UICollectionViewCell {

        let cell :YFWaterFallCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(self.cellID, forIndexPath: indexPath) as!YFWaterFallCollectionViewCell

        cell.model =self.dataLists[indexPath.row]

        return cell

    }

    

    //layout代理

    func waterFallLayout(layout:UICollectionViewFlowLayout, index:NSInteger, width: CGFloat) -> CGFloat {

        let model :YFVideoInfo =self.dataLists[index]

        return width / (CGFloat((model.w?.floatValue)!) / CGFloat((model.h?.floatValue)!))

    }

    

    func columnCountOfWaterFallLayout(layout:UICollectionViewFlowLayout) ->NSInteger {

        return2

    }

    

    overridefunc didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

    }


}

2.cell設定,重新layoutSubviews,防止錯位

import UIKit

class YFWaterFallCollectionViewCell:UICollectionViewCell {

    //資料被賦值時初始化item資料

    var model :YFVideoInfo? {

        didSet {

            let url =NSURL(string:"http://xxx.xxx.cn\(model!.videoImgUrl)")

            self.imageView.sd_setImageWithURL(url)

        }

    }

    let imageView :UIImageView =UIImageView()

    overrideinit(frame:CGRect) {

       super.init(frame: frame)

        self.imageView.frame =CGRectMake(0,0, frame.size.width, frame.size.height)

        self.addSubview(self.imageView)

    }

    

    requiredinit?(coder aDecoder:NSCoder) {

        fatalError("init(coder:) has not been implemented")

    }

    

    //重新布局,否則二次重新整理時由於儲存格重用導致錯位

    overridefunc layoutSubviews() {

        super.layoutSubviews()

        self.imageView.frame =CGRectMake(0,0,self.frame.size.width,self.frame.size.height)

    }

    

}

3.自訂UICollectionViewFlowLayout類

import UIKit

protocol YFWaterFallLayoutDelegate {

    // 返回index位置下的item的高度

    func waterFallLayout(layout:UICollectionViewFlowLayout,index :NSInteger,width :CGFloat) ->CGFloat

    // 返回瀑布流顯示的列數

    func columnCountOfWaterFallLayout(layout:UICollectionViewFlowLayout) ->NSInteger

}


class YFWaterFallCollectionLayout:UICollectionViewFlowLayout {

    var delegate :YFWaterFallLayoutDelegate?

    var attributesArray = [UICollectionViewLayoutAttributes]()//布局資訊儲存,防止下拉看到二次地區時,多次返回布局資訊。

    var columnHeights =Array<Float>()//儲存當前行的列的高度資訊。

    var columnCount :Int =2//預設列數

    var edgeInsets :UIEdgeInsets =UIEdgeInsets(top:5, left: 5, bottom:5, right:5)

    var columnMargin :CGFloat =5//列距

    var rowMargin :CGFloat =5//行距

    

    overridefunc prepareLayout() {

        super.prepareLayout()

        //初始化最大高度資料集合

        columnHeights =Array<Float>()

        self.columnCount = (self.delegate?.columnCountOfWaterFallLayout(self))!

        ifself.columnCount <=0 {

            return;

        }

        for_in0..<columnCount {

            columnHeights.append(Float(self.edgeInsets.top))

        }

        //初始化布局資訊資料來源

        attributesArray = [UICollectionViewLayoutAttributes]()

        let cellCount =self.collectionView!.numberOfItemsInSection(0)

        for iin0..<cellCount {

            let indexPath = NSIndexPath(forItem:i, inSection:0)

            let attributes =self.layoutAttributesForItemAtIndexPath(indexPath)

            attributesArray.append(attributes!)

        }

    }

    

    // 所有儲存格位置屬性

    overridefunc layoutAttributesForElementsInRect(rect:CGRect)

        -> [UICollectionViewLayoutAttributes]? {

        returnself.attributesArray

    }

    

    // 這個方法返回每個儲存格的位置和大小

    overridefunc layoutAttributesForItemAtIndexPath(indexPath:NSIndexPath) -> UICollectionViewLayoutAttributes? {

        let attribute =UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

        let collectionViewWidth :CGFloat =self.collectionView!.frame.size.width

        let width :CGFloat = (collectionViewWidth -self.edgeInsets.left -self.edgeInsets.right - (CGFloat(self.columnCount) - 1) * self.columnMargin) /CGFloat(self.columnCount);

        // 計算當前item應該擺放在第幾列(計算哪一列高度最短)

        var minColumn :Int =0//預設是第0列

        var minHeight :Float =MAXFLOAT

        // 遍曆找出最小高度的列,在最小列的下面新增。

        for (index,value)inself.columnHeights.enumerate() {

            if minHeight > value {

                minHeight = value

                minColumn = index

            }

        }

        let x :CGFloat =self.edgeInsets.left +CGFloat(minColumn) * (width +self.columnMargin)

        let y :CGFloat =CGFloat(minHeight) +self.rowMargin

        let height :CGFloat = (self.delegate?.waterFallLayout(self, index: indexPath.row, width: width))!

        attribute.frame =CGRectMake(x, y, width, height)

//        // 更新數組中的最短列的高度

        self.columnHeights[minColumn] =Float(y + height)

        return attribute

    }

   &nbs

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.