swift简单瀑布流的实现



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

    }

    

    // 内容区域总大小,不是可见区域

    overridefunc collectionViewContentSize() ->CGSize {

        //每次加载时,重新计算最大高度。防止多次下拉时看不到更多区域。

        var maxHeight :Float =0

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

            if value > maxHeight {

                maxHeight = value

            }

        }

        returnCGSizeMake(0,CGFloat(maxHeight) + self.edgeInsets.top)

    }

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值