CollectionView实现瀑布流(swift)
2016-01-14 20:39
435 查看
我们用纯代码实现一下瀑布流:
AppDelegate:
搞一个随机色:
自定义布局:
一个类继承UICollectionViewController,遵循:WaterFlowViewLayoutDelegate协议
其实就是一个自定义布局 算术的问题,看一下效果:
AppDelegate:
[code]var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { window = UIWindow(frame: (UIScreen.mainScreen().bounds)) window?.rootViewController = WaterFlowViewController() window?.makeKeyAndVisible() return true }
搞一个随机色:
[code]extension UIColor { //随机颜色 class func randomColor() ->UIColor { return UIColor(red: randomValue(), green: randomValue(), blue: randomValue(), alpha: 1) } class func randomValue()->CGFloat { return CGFloat(arc4random_uniform(256))/255 } }
自定义布局:
[code]protocol WaterFlowViewLayoutDelegate:NSObjectProtocol { //collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) ///width是瀑布流每列的宽度 func waterFlowViewLayout(waterFlowViewLayout:WaterFlowViewLayout,heightForWidth:CGFloat,atIndextPath:NSIndexPath)->CGFloat } class WaterFlowViewLayout: UICollectionViewLayout { weak var delegate:WaterFlowViewLayoutDelegate? ///所有cell的布局属性 var layoutAttributes = [UICollectionViewLayoutAttributes]() ///使用一个字典记录每列的最大Y值 var maxYDict = [Int:CGFloat]() static var Margin:CGFloat = 8 ///瀑布流四周的间距 var sectionInsert = UIEdgeInsets(top: Margin, left: Margin, bottom: Margin, right: Margin) //列间距 var columnMargin:CGFloat = Margin //行间距 var rowMargin:CGFloat = Margin ///瀑布流列数 var column = 4 var maxY:CGFloat = 0 var columnWidth:CGFloat = 0 ///prepareLayout会在调用collectionView.reloadData() override func prepareLayout() { //设置布局 //需要清空字典里面的值 for key in 0..<column { maxYDict[key] = 0 } //清空之前的布局属性 layoutAttributes.removeAll() //清空最大列的Y值 maxY = 0 ///清空列宽 columnWidth = 0 //计算每列的宽度,需要在布局之前算好 columnWidth = (UIScreen.mainScreen().bounds.width - sectionInsert.left - sectionInsert.right - (CGFloat(column) - 1)*columnMargin)/CGFloat(column) let number = collectionView?.numberOfItemsInSection(0) ?? 0 for i in 0..<number { //布局每一个cell的frame let layoutAttr = layoutAttributesForItemAtIndexPath(NSIndexPath(forItem: i, inSection: 0))! layoutAttributes.append(layoutAttr) } calcMaxY() } func calcMaxY(){ //获取最大这一列的Y //默认第0列最长 var maxYCoulumn = 0 //for 循环比较,获取最长的这列 for (key,value) in maxYDict { if value > maxYDict[maxYCoulumn]{ //key这列的Y值是最大的 maxYCoulumn = key } } //获取到Y值最大的这一列 maxY = maxYDict[maxYCoulumn]! + sectionInsert.bottom } //返回collectionViewContentSize 大小 override func collectionViewContentSize() -> CGSize { return CGSize(width: UIScreen.mainScreen().bounds.width, height: maxY) } // 返回每一个cell的布局属性(layoutAttributes) // UICollectionViewLayoutAttributes: 1.cell的frame 2.indexPath override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { assert(delegate != nil,"瀑布流必须实现代理来返回cell的高度") let height = delegate!.waterFlowViewLayout(self, heightForWidth: columnWidth, atIndextPath: indexPath) // 找到最短的那一列,去maxYDict字典中找 // 最短的这一列 var minYColumn = 0 //通过for循环去和其他列比较 for(key, value) in maxYDict { if value < maxYDict[minYColumn] { minYColumn = key } } // minYColumn 就是短的那一列 let x = sectionInsert.left + CGFloat(minYColumn) * (columnWidth + columnMargin) //最短这列的Y值 + 行间距 let y = maxYDict[minYColumn]! + rowMargin //设置cell的frame let frame = CGRect(x: x, y: y, width: columnWidth, height: height) //更新最短这列的最大Y值 maxYDict[minYColumn] = CGRectGetMaxY(frame) //创建每个cell对应的布局属性 let layoutAttr = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) layoutAttr.frame = frame return layoutAttr } //预加载下一页数据 override func layoutAttributesForElementsInRect(rect:CGRect) -> [UICollectionViewLayoutAttributes]{ return layoutAttributes } }
一个类继承UICollectionViewController,遵循:WaterFlowViewLayoutDelegate协议
[code]class WaterFlowViewController: UICollectionViewController,WaterFlowViewLayoutDelegate { let ReuseIdentifier = "ReuseIdentifier" let layout = WaterFlowViewLayout() init(){ super.init(collectionViewLayout: layout) } override func viewDidLoad() { super.viewDidLoad() collectionView?.backgroundColor = UIColor.whiteColor() collectionView?.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: ReuseIdentifier) layout.delegate = self } func waterFlowViewLayout(waterFlowViewLayout: WaterFlowViewLayout, heightForWidth: CGFloat, atIndextPath: NSIndexPath) -> CGFloat { return CGFloat(100 + arc4random_uniform(50)) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 500 } override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier(ReuseIdentifier, forIndexPath: indexPath) cell.backgroundColor = UIColor.randomColor() return cell } }
其实就是一个自定义布局 算术的问题,看一下效果:
相关文章推荐
- Swift语言教程中文文档
- Swift 学习 用 swift 调用 oc
- swift for、for-in循环
- Swift iOS项目最佳实践汇总
- iOS_Swift之UICollectionView详解
- Swift-04-Designated&&Convenience
- swift_多线程基础_最简单用法(GCD, NSOperationQueue, NSThread)
- swift-03-构造器(Designated&&Convenience)
- Swift 变量与常量
- Swift之UITableView的增删以及三种逆向传值方式
- Swift 编程语言入门教程
- Swift - 使用NSURL进行数据的提交和获取(POST与GET)
- 苹果Swift语言中文简明教程
- IOS反射,swift反射,基础 MODEL转字典,字典转MODEL,根据下面的自己进行拓展
- swift中对AFNetWorking的简单封装
- 【同行说技术】swift最全学习资料汇集(一)
- Swift UITableView
- Swift内存管理(ARC)之循环引用
- Swift中的实例方法--柯里化方法(Curried Functions)
- swift NSDictionary(字典)