UICollectionView

---恢复内容开始---

(一)使用UITableView进行表格搭建是可以的。但是UITableView也有自己的局限性。对于一些更加复杂的布局,就会不太方便。例如UITableView只可以纵向排序,每一行只能有一个数组载体cell,不支持一行排列多个。这时候一般会用到UICollectionView。现在app的照片查看,九宫格排布,瀑布流等用的都是UICollectionView。

(二)UICollectionView的优势:

  (1)支持水平和垂直布局

  (2)通过UICollectionViewLayOut类配置的方式进行布局

  (3)相比于TableView的Cell,CollectionView的数据载体Item的大小和位置更加灵活

  (4)通过UICollectionViewLayOutDelegate协议可以动态的对布局进行重设

  (5)通过独立的LayOut类来布局,layOut存放着每个item的布局信息,大小,位置,3D变换等。

(三)九宫格实现:

  (1)首先自定义UICollectionView,并且懒加载添加到控制器中

 // 懒加载CollectionView
    private lazy var collectionView : SGCollectionView = {
        
       let collectionView = SGCollectionView(frame: CGRectZero, collectionViewLayout: UICollectionViewFlowLayout())
        
        return collectionView
        
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        collectionView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 300)
        
    }

  效果:此时是一个黑色的,没有经过任何设置的CollectionView

  (2)在自定义的SGCollectionView中进行设置:

    2.1成为代理,设置layout

    // 注意:这里面是拿不到item标准的frame的,无法计算
    private func setupUI() {
    
        backgroundColor = UIColor.whiteColor()
        // 设置代理和数据源
        self.delegate = self
        self.dataSource = self
        
        // 注册item
        self.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: ITEMID)
    }
    
    // 在这里设置layout
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 系统的流试布局
        let layout = collectionViewLayout as! UICollectionViewFlowLayout
        // 横纵间距
        layout.minimumLineSpacing = margin
        layout.minimumInteritemSpacing = margin
        // 布局方向,分水平和垂直
        layout.scrollDirection = .Vertical
        let itemWH = CGFloat(Int((self.frame.width - 2 * margin) / 3))
        // 每个item的尺寸
        layout.itemSize = CGSize(width: itemWH, height: itemWH)
    }

    2.2实现代理

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 9
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        
        let item = collectionView.dequeueReusableCellWithReuseIdentifier(ITEMID, forIndexPath: indexPath)
        
        item.backgroundColor = RandomColor()
        
        return item
    }
  

效果:

此时如果想要让每个item显示别的,例如图片按钮云云,只需自定义UICollectionViewCell即可。

(三)创建更加灵活的流试布局:UICollectionViewDelegateFlowLayout协议中电柜了很多布局方法。

UICollectionViewDelegateFlowLayout协议:

public protocol UICollectionViewDelegateFlowLayout : UICollectionViewDelegate {
    
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize
    @available(iOS 6.0, *)
    optional public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
}

设置每个item的尺寸大小:

  // 设置每个item的大小
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        
        if indexPath.row%2 == 0 {
            return CGSizeMake(50, 50)
        }else {
            return CGSizeMake(100, 100)
        }
        
    }

效果:

(四)自定义UICollectionViewFlowLayout进行参差瀑布流布局:所谓瀑布流效果,就是分成两列或者多列进行数据战术。每条数据(item)高度也不同,形成了参差不齐的效果。使用原生的UICollectionViewFlowLayout很难做到。这时候我们只能自定义。

 代码:

//
//  SGLayout.swift
//  SGCollectionView
//
//  Created by 艾小新 on 16/9/1.
//  Copyright © 2016年 xiaoxin. All rights reserved.
//

import UIKit

class SGLayout: UICollectionViewFlowLayout {
    
    // 布局多少item
    var itemCount: Int = 0
    
    // 数组保存 每个item的设置
    var attributeArray: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
    
    
    // 布局前准备会调用
    override func prepareLayout() {
        
        
        super.prepareLayout()
        
        // 定义2纵向列
        // 计算每一个item的宽高
        let width = (UIScreen.mainScreen().bounds.size.width - self.sectionInset.left - self.sectionInset.right - self.minimumInteritemSpacing)/2
        
        var heigh = [self.sectionInset.top,self.sectionInset.bottom]
        
        for i in 0..<itemCount {
            
            // 设置每个item位置
            let index = NSIndexPath(forItem: i, inSection: 0)
            // 创建布局
            let attris = UICollectionViewLayoutAttributes(forCellWithIndexPath: index)
            // 随机高度
            let randH = CGFloat(arc4random()%150 + 40)
            // 那一列高度最小,就放到下面,标记最短的列
            var widL  = 0
            
            if heigh[0] < heigh[1] {
                
                heigh[0] = heigh[0] + randH + self.minimumLineSpacing
                widL = 0
            } else {
                heigh[1] = heigh[1] + randH + self.minimumLineSpacing
                widL = 1
                
            }
            
            // 设置item位置
            attris.frame = CGRectMake(self.sectionInset.left + (self.minimumInteritemSpacing + width) * CGFloat(widL) , heigh[widL] - randH - self.minimumLineSpacing, width, randH)
            
            attributeArray.append(attris)
            
            
          
        }
        if heigh[0] > heigh[1] {
            
            self.itemSize = CGSizeMake(width, heigh[0] - self.sectionInset.top * 2 / CGFloat(itemCount) - self.minimumLineSpacing )
        } else {
            
            self.itemSize = CGSizeMake(width, heigh[1] - self.sectionInset.top * 2 / CGFloat(itemCount) - self.minimumLineSpacing )
        }
        
    }
    
    
    // 这个方法返回布局数组
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        
        
        return attributeArray
    }
    

}

注意:prepareLayout会调用很多很多次。

效果:

至于瀑布流会另开一篇 单独分析。

UICollectionView的布局原理就是用LayOut类对每个item进行布局设置,具体配置信息是由UICollectionViewLayOutAttributes来存储的。

posted @ 2016-09-01 18:22  三更小新  阅读(632)  评论(0编辑  收藏  举报