//
// 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
}
}