思路:类比tableView的多种cell显示,通过操作UICollectionView的分组实现,当只有一种cell时通常会直接创建FlowLayout,但是有多种cell时,不同的cell还有itemSize的区别,所以不能直接设置FlowLayout的值,而是通过代理判断不同情况下itemSize的值
效果如图:
开始编码:
Step1:懒加载UICollectionView
注意点1:虽然我们的layout设置时在代理中,我们也要创建一个layout否则会爆这个错 -> 'UICollectionView must be initialized with a non-nil layout parameter'
注意点2:这里的layout是UICollectionViewFlowLayout 而不是 UICollectionViewLayout,因为我们实现的是UICollectionViewFlowLayout的代理方法(UICollectionViewDelegateFlowLayout)
lazy var collectionView:UICollectionView = {
let layout = UICollectionViewFlowLayout.init()
let collectionView = UICollectionView.init(frame: self.view.bounds, collectionViewLayout: layout)
collectionView.backgroundColor = .clear
//注册cell
collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: CellID01)
collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: CellID02)
collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: CellID03)
//注册头部
collectionView.register(Demo05HeaderView.classForCoder(), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HeaderID)
//设置数据源代理
collectionView.dataSource = self
// 设置flowlayout的代理,用于控制itemSize等
collectionView.delegate = self
return collectionView
}()
Step2:实现数据源代理方法(UICollectionViewDataSource)
extension ViewController05: UICollectionViewDataSource {
//有多少的分组
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
//每组有多少个item
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 1
}else if section == 1{
return 5
}else{
return 10
}
}
//
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellID01, for: indexPath)
cell.backgroundColor = UIColor.systemGreen
return cell
}else if indexPath.section == 1{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellID02, for: indexPath)
cell.backgroundColor = UIColor.systemRed
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellID03, for: indexPath)
cell.backgroundColor = UIColor.systemBlue
return cell
}
}
//头部
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HeaderID, for: indexPath) as! Demo05HeaderView
view.titleLabel.text = "第\(indexPath.section)组"
return view
}else{
fatalError("No Such kind")
}
}
}
Step3:实现FlowLayout代理方法UICollectionViewDelegateFlowLayout
extension ViewController05: UICollectionViewDelegateFlowLayout{
//设置头部的尺寸
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize.init(width: self.view.bounds.width, height: 35)
}
//itemSize
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
switch indexPath.section {
case 0:
return CGSize.init(width: self.view.bounds.width, height: 150)
case 1:
return CGSize.init(width: (self.view.bounds.width - 30) / 2, height: 45)
default:
return CGSize.init(width: (self.view.bounds.width - 40) / 3, height: 25)
}
}
// 设置 minimumLineSpacing 水平间隔
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
switch section {
case 0:
return 1
case 1:
return 2
default:
return 5
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
}
备注:HeaderView的实现
class Demo05HeaderView: UICollectionReusableView {
lazy var titleLabel:UILabel = {
let titleLabel = UILabel.init(frame: CGRect.init(x: self.redView.frame.maxX+15, y: 5, width: 150, height: self.frame.size.height-10))
titleLabel.textColor = .black
titleLabel.font = UIFont.systemFont(ofSize: 16)
return titleLabel
}()
lazy var redView:UIView = {
let redView = UIView.init(frame: CGRect.init(x: 20, y: 5, width: 5, height: self.frame.size.height-10))
redView.backgroundColor = UIColor.init(red:203/255.0, green:13/255.0, blue:29/255.0, alpha:1)
return redView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.redView)
self.addSubview(self.titleLabel)
self.backgroundColor = UIColor.init(red:243/255.0, green:243/255.0, blue:243/255.0, alpha:1)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}