UIKit:UICollection自定义MyLayout

//
//  MyLayout.swift
//  UIKitTest
//
//  Created by travey on 2018/11/10.
//  Copyright © 2018 ZhouShijie. All rights reserved.
//

import UIKit

// 设置一个自己的布局
// 因为还是流式的,所以直接继承流式布局就好了,剩下的自己定义
class MyLayout: UICollectionViewFlowLayout {
    
    var itemCount: Int! // 定义方块的个数
    var attributeArray: Array<UICollectionViewLayoutAttributes>? // 定义一个UICollectionViewLayoutAttributes类型的数组,对应相应方块的属性
    
    // 下面是必须要重写的方法
    override func prepare() {
        super.prepare() // 先调用一下父类
        // 实例化数组
        attributeArray = Array<UICollectionViewLayoutAttributes>()
        // 取方块的宽度为屏幕的一半
        let width = CGFloat((UIScreen.main.bounds.width - minimumInteritemSpacing) / 2)
        // 保存当前当前左右两侧的高度,初始值为0
        var leftHeight: CGFloat = 0.0
        var rightHeight: CGFloat = 0.0
        // 临时变量,保存还没添加方块之前,对应一侧的高度,并将其赋值给新加方块的y值
        var originalHeight: CGFloat!
        
        // 遍历每个方块
        for i in 0 ..< itemCount {
            // UICollectionViewLayoutAttributes属性中有一个属性叫做open var indexPath: IndexPath,即代表当前方块属于哪一个section,他位于当前section中的第几个,所以要定义一个indexPath的一个临时变量,将attri元素初始化的时候就要将其indexPath初始化成第0节,编号为i
            // 对于数组中的每个元素,主要设置他们的frame以及indexPath就行了
            let indexPath = IndexPath(item: i, section: 0)
            let attri = UICollectionViewLayoutAttributes(forCellWith: indexPath) // 数组内部元素实例化,indexPath必须给注明了
            let height = CGFloat(arc4random() % 340 + 50) // 定义当前方块的高度,范围是50~390
            print(CGFloat(arc4random() % 340 + 50))
            // 如果左边低,就放在左边,并且让originalHeight的值等于原height
            if leftHeight <= rightHeight {
                originalHeight = leftHeight
                leftHeight = leftHeight + height + self.minimumLineSpacing
                attri.frame = CGRect(x: 0, y: originalHeight, width: width, height: height)
            } else {
                originalHeight = rightHeight
                rightHeight = rightHeight + height + self.minimumLineSpacing
                attri.frame = CGRect(x: width + minimumInteritemSpacing, y: originalHeight, width: width, height: height)
            }
            attributeArray?.append(attri) // 添加
        } // for
        
        // 100个方块太多了,一个屏幕肯定放不下,因此我们要设置该类的itemSize的方法,这里的itemSize是个估计值,取左右最长高度除以总个数再减去行间距,这样就能大概估出一个方块的具体高度,以可以滑动显示
        if leftHeight <= rightHeight {
            self.itemSize = CGSize(width: width, height: rightHeight * 2 / CGFloat(itemCount) - self.minimumLineSpacing)
        } else {
            self.itemSize = CGSize(width: width, height: leftHeight * 2 / CGFloat(itemCount) - self.minimumLineSpacing)
        }
    }
    
    // 这个方法也必须要重写,返回一个属性的数组
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attributeArray
    }

}
//
//  ViewController.swift
//  UIKitTest
//
//  Created by travey on 2018/11/9.
//  Copyright © 2018 ZhouShijie. All rights reserved.
//

import UIKit

// 这里继承了UICollectionViewDelegateFlowLayout,这个类是UICollectionViewDelegate的子类,因此无需再次继承UICollectionViewDelegate
class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // 先实例化布局
        let myLayout = MyLayout()
        myLayout.itemCount = 100 // 有100个方块
        let collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: myLayout) // 网格实例化
        collectionView.register(NSClassFromString("UICollectionViewCell"), forCellWithReuseIdentifier: "cell") // 注册网格
        // 委托
        collectionView.delegate = self
        collectionView.dataSource = self
        self.view.addSubview(collectionView)
        
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 100
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) // 从缓冲池里取
        cell.backgroundColor = UIColor(displayP3Red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1) // 设置颜色,注意这里drand48()返回一个0~1之间的随机数哦~
        return cell
    }
    
}

猜你喜欢

转载自blog.csdn.net/shijie97/article/details/83928770