您的位置:首页 > 移动开发 > Swift

swift瀑布流自定义布局实现

2016-04-29 11:58 465 查看
demo github下载地址
https://github.com/liwei5bao/SwiftWaterfallProject
//  ViewController.swift

//  SwiftWaterfall

import UIKit

import UIKit

class ViewController:UIViewController{

    
   var collectionView:UICollectionView?

    ///重用item的标识
   let itwmID =
"shopID"

    ///商品数组
   lazy
var shops:NSMutableArray? = {

        

        returnNSMutableArray()

        
    }()

    
   override
func viewDidLoad() {
       super.viewDidLoad()

        
       //初始化布局
       self.setupLayout()

        //初始化上拉加载更多,下拉加载

        self.setupRefresh()

        self.loadNewShops()
    }

    

    //MARK:初始化数据
   private
func setupList(){

        
       for i
in 0...10{

            
           var model:NSDictionary?

            
           if
Int(i % 2) ==
0{

                

                model = ["w":NSNumber(int:200),"h":NSNumber(int:300),"img":"http://s6.mogujie.cn/b7/bao/131008/q2o17_kqyvcz3ckfbewv3wgfjeg5sckzsew_330x445.jpg_200x999.jpg","price":""]

                
            }else{

                

                model = ["w":NSNumber(int:200),"h":NSNumber(int:400),"img":"http://s6.mogujie.cn/b7/bao/131008/q2o17_kqyvcz3ckfbewv3wgfjeg5sckzsew_330x445.jpg_200x999.jpg","price":""]
            }

            
           self.shops?.addObject(model!)
        }

        self.collectionView?.header.endRefreshing()

        self.collectionView?.footer.endRefreshing()
    }

    

    //MARK:初始化的内容
   private
func setupRefresh(){

        

        self.collectionView?.addLegendHeaderWithRefreshingTarget(self,
refreshingAction: "loadNewShops")//header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: "loadNewShops")

        self.collectionView?.addLegendFooterWithRefreshingTarget(self,
refreshingAction: "loadMoreShops")//footer = MJRefreshAutoFooter(refreshingTarget: self, refreshingAction: "loadMoreShops")

        self.collectionView?.footer.hidden =true
    }

    
   private
func setupLayout(){

        
       let layout =
OOWaterflowLayout()
        layout.delegate =self

        //创建collectionView
       let collectionView =
UICollectionView(frame:
self.view.bounds, collectionViewLayout: layout)
        collectionView.backgroundColor =UIColor.whiteColor()
        collectionView.dataSource =self
       self.view.addSubview(collectionView)
        collectionView.registerNib(UINib(nibName:"OOShopCell", bundle:
nil), forCellWithReuseIdentifier:
itwmID)
       self.collectionView = collectionView

        
    }

    

    

    ///加载新数据
   func loadNewShops(){

        

        self.shops?.removeAllObjects()
       self.setupList()
       //刷新数据

        self.collectionView?.reloadData()

        self.collectionView?.header.endRefreshing()
    }

    

    ///加载更多的数据
   func loadMoreShops(){

        
       self.setupList()
       //刷新数据

        self.collectionView?.reloadData()

        self.collectionView?.footer.endRefreshing()

        
    }

    
   override
func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        
    }

    
}

extension ViewController:UICollectionViewDataSource{

    

    //MARK:UICollectionViewDataSource的数据源
   func collectionView(collectionView:
UICollectionView, numberOfItemsInSection section:
Int) -> Int {

        

        self.collectionView?.footer.hidden = (self.shops?.count
== 0)
       return (self.shops?.count)!
    }

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

        
       let cell = collectionView.dequeueReusableCellWithReuseIdentifier(itwmID,
forIndexPath: indexPath)as?
OOShopCell
        cell?.shops =self.shops![indexPath.item]as?
NSDictionary
       return cell!
    }

    
}

extension ViewController:OOWaterflowLayoutDeledate{

    

    ///必须实现的方法
   func waterflowLayout(waterflowLayout waterflowLayout:OOWaterflowLayout, heightForItemAtIndex index:NSInteger,
itemWidth width: CGFloat) ->
CGFloat {

        
       let shop =
self.shops![index]as!
NSDictionary
       return width *
CGFloat(shop["h"]as!
NSNumber) /CGFloat(shop["w"] as!
NSNumber)
    }

    

    //MARK:下边的代理可以不实现有默认值

    ///返回列数
   func columnCountInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->
NSInteger {

        
       return
2
    }

    

    ///返回列间距
   func columnMarginInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->
CGFloat {

        
       return
10
    }

    

    ///返回行间距
   func rowMarginInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->
CGFloat {

        
       return
10
    }

    

    ///返回内边距
   func edgeInsetsInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->
UIEdgeInsets {

        
       return
UIEdgeInsetsMake(20,10,
10, 10)
    }
}

//  OOWaterflowLayout.swift

//  swift瀑布流

import UIKit

class OOWaterflowLayout:UICollectionViewLayout {

    ///代理

    weakvar delegate:OOWaterflowLayoutDeledate?

    ///默认的列数
   let OODefaultColumnCount:NSInteger =2

    /**
每一列之间的间距 */
   let OODefaultColumnMargin:CGFloat =10

    /**
每一行之间的间距 */
   let OODefaultRowMargin:CGFloat =10

    /**
边缘间距 */
   let OODefaultEdgeInsets:UIEdgeInsets =UIEdgeInsetsMake(10,10,
10, 10)

    

    /**
存放所有cell的布局属性 */

    lazyvar attrsArray:[UICollectionViewLayoutAttributes]
= {return [UICollectionViewLayoutAttributes]()}()

    /**
存放所有列的当前高度 */
   lazy
var columnHeights:NSMutableArray = {returnNSMutableArray()}()
   var contentHeight:CGFloat?

    

    ///行间距
   var rowMargin:CGFloat{

        
       get{

            

            if ((self.delegate?.respondsToSelector("rowMarginInWaterflowLayout:"))
== true){

            
               return (self.delegate?.rowMarginInWaterflowLayout!(self))!
            }else{

            

                returnOODefaultRowMargin
            }

            
        }

        
    }

    

    ///列间距
   var columnMargin:CGFloat{

        
       get{

            

            if ((self.delegate?.respondsToSelector("columnMarginInWaterflowLayout:"))
== true){

                
               return (self.delegate?.columnMarginInWaterflowLayout!(self))!
            }else{

                

                returnOODefaultColumnMargin
            }

            
        }
    }

    

    ///列数
   var columnCount:NSInteger{

        
       get{

            

            if ((self.delegate?.respondsToSelector("columnMarginInWaterflowLayout:"))
== true){

                
               return (self.delegate?.columnCountInWaterflowLayout!(self))!
            }else{

                

                returnOODefaultColumnCount
            }

            
        }
    }

    

    ///边距
   var edgeInsets:UIEdgeInsets{

        
       get{

            

            if ((self.delegate?.respondsToSelector("edgeInsetsInWaterflowLayout:"))
== true){

                
               return (self.delegate?.edgeInsetsInWaterflowLayout!(self))!
            }else{

                

                returnOODefaultEdgeInsets
            }

            
        }
    }

}

//MARK:初始化和计算

extension OOWaterflowLayout{

    ///1.布局的初始化操作
   override
func prepareLayout() {

        super.prepareLayout()

        

        self.contentHeight =0

        //清除之前计算的高度

        self.columnHeights.removeAllObjects()
       for
_ in
0...self.columnCount -1{

        

            self.columnHeights.addObject(self.edgeInsets.top)
        }

        

        //清除之前所有的布局属性

        self.attrsArray.removeAll()

        

        //创建每一个cell的布局属性

        let count =self.collectionView?.numberOfItemsInSection(0)
       for
var i =0;i < count;i++ {

        
           let indexpath =
NSIndexPath(forItem: i, inSection:0)
           //获取布局属性

            let attrs =self.layoutAttributesForItemAtIndexPath(indexpath)
           self.attrsArray.append(attrs!)
        }

        
    }

    ///2.决定cell的排布
   override
func layoutAttributesForElementsInRect(rect:CGRect) -> [UICollectionViewLayoutAttributes]? {

        
       return
self.attrsArray
    }

    

    ///3.返回indexPath位置cell对应的布局属性
   override
func layoutAttributesForItemAtIndexPath(indexPath:NSIndexPath) ->
UICollectionViewLayoutAttributes? {

        

        //创建布局属性
       let attrs =
UICollectionViewLayoutAttributes(forCellWithIndexPath:indexPath)

        //创建collectionView的宽度
       let collectionViewW =
self.collectionView?.frame.size.width
       let coCount:CGFloat =CGFloat(NSNumber(integer:self.columnCount))

        //设置布局的frame
       let w:CGFloat = (collectionViewW! -self.edgeInsets.left
-self.edgeInsets.right - (coCount -1) *
self.columnMargin) / coCount
       let h:CGFloat = (self.delegate?.waterflowLayout(waterflowLayout:self,
heightForItemAtIndex: indexPath.item, itemWidth: w))!

        

        //找出高度最短的那一列
       var destColumn:CGFloat =0
       var minColumnHeight:CGFloat = (self.columnHeights[0]as?
CGFloat)!
       for
var i =1;i <
self.columnCount;i++ {

            
           let columnHeight = (self.columnHeights[i]as?
CGFloat)!
           if minColumnHeight > columnHeight{

            
                minColumnHeight = columnHeight
                destColumn =CGFloat(i)
            }
        }

        
       let x:CGFloat =self.edgeInsets.left
+ destColumn * (w +self.columnMargin)
       var y:CGFloat = minColumnHeight
       if y !=
self.edgeInsets.top{

        
            y +=self.rowMargin
        }

        
        attrs.frame =CGRectMake(x, y, w, h)

        

        //更新最短的那一列的高度
       self.columnHeights[NSInteger(destColumn)] =CGRectGetMaxY(attrs.frame)

        

        //记录内容的高度
       let columnHeight:CGFloat =self.columnHeights[NSInteger(destColumn)]as!
CGFloat

        
       if
self.contentHeight < columnHeight{

        
           self.contentHeight = columnHeight
        }

        
       return attrs
    }

    

    
   override
func collectionViewContentSize() ->CGSize {

        returnCGSizeMake(0,self.contentHeight!
+self.edgeInsets.bottom)

    }

    
}

//MARK:代理
@objcprotocol OOWaterflowLayoutDeledate:NSObjectProtocol{

    ///返回每个item的高度必须实现
   func waterflowLayout(waterflowLayout waterflowLayout:OOWaterflowLayout,heightForItemAtIndex index:NSInteger,itemWidth
width:CGFloat)->CGFloat

    ///返回的列数不实现默认为3列
   optional
func columnCountInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->NSInteger

    ///返回列间距,默认为10
   optional
func columnMarginInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->CGFloat

    ///返回行间距,默认为10
   optional
func rowMarginInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->CGFloat

    ///返回内边距,默认为(10,10,10,10)
   optional
func edgeInsetsInWaterflowLayout(waterflowLayout:OOWaterflowLayout) ->UIEdgeInsets

    
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息