前言:
最近遇到一个磨人的需求。
背景:我们的首页用的是 UICollectionView。在这个collectionview的底部,放一个FooterView,用来写点提示信息。
要求:
1、如果collectionview的内容比较少(也就是说:collectionView.frame.height > collectionView.contentSize.height),那么这个FooterView就直接放到collectionview的底部。
2、如果collectionview的内容比较多(也就是说:collectionView.frame.height < collectionView.contentSize.height),那么这个FooterView就需要跟随collectionview滚动。
如果是在UITableView上,我们可以这么干:
let tableView = UITableView()
tableView.tableFooterView = UIView()
但是在 UICollectionView 上,我没有点出来这个footerview的属性。这就很尴尬了。我去网上搜了一下,发现大家用的都是SectionHeader的办法。那这就有个问题了,SectionFooter 也是能写的,但是在collectionview内容比较少的时候,这个SectionFooter并不会放在collectionview的最底部,会放在屏幕中间。我家UI设计员肯定不会提意见
然后,我想了很久。决定伪造一下FooterView。
Swift
代码地址:https://github.com/gityuency/Autolayout
示例代码类名 【FakeCollectionViewController】
示例效果
思路:
第一步:使用UIEdgeInsets来给collectionview底部设置一个缩进。
第二步:给collectionview添加一个视图,用来做FooterView。
第三步:在代理方法里面拿到collectionview的内容高度,给这个FooterView设置一下Frame。
代码:
import UIKit
class FakeCollectionViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
/// 复用 ID
let rid = "rid"
/// 单元格个数
var cellcount = 10
/// FooterView的高度
let FooterHeight: CGFloat = 60
/// 记录 collectionview 的内容高度
var contentHeight: CGFloat = 0
/// 放在底部的View
lazy var footerView: UIButton = {
let b = UIButton()
b.setTitle("点击 FooterView", for: UIControl.State.normal)
b.backgroundColor = UIColor.brown
b.addTarget(self, action: #selector(click), for: .touchUpInside)
return b
}()
@objc func click() {
print("测试是否可以点击")
}
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11.0, *) {
collectionView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: rid)
collectionView.addSubview(footerView)
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: FooterHeight, right: 0)
// contentSize 是不包括 EdgeInsets的
}
}
extension FakeCollectionViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cellcount
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: rid, for: indexPath)
cell.backgroundColor = UIColor.orange
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
cellcount += 10
collectionView.reloadData()
}
// 在这个方法里面可以拿到视图的内容高度
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if contentHeight == collectionView.contentSize.height { //如果内容高度没有变化,就不需要设置footer的位置
return
}
contentHeight = collectionView.contentSize.height
if collectionView.frame.height > collectionView.contentSize.height + FooterHeight { //当视图的高度 比 (内容高度 + Footer高度) 大的时候
DispatchQueue.main.async {
print("直接放到collectionview的底部: \(collectionView.contentSize.height)")
let w = collectionView.bounds.width
let y = collectionView.frame.height - self.FooterHeight
self.footerView.frame = CGRect(x: 0, y: y, width: w, height: self.FooterHeight)
}
} else {
DispatchQueue.main.async {
print("根据内容高度调整到底部: \(collectionView.contentSize.height)")
let w = collectionView.bounds.width
let y = collectionView.contentSize.height
self.footerView.frame = CGRect(x: 0, y: y, width: w, height: self.FooterHeight)
}
}
}
}
//if (cellcount - 1) == collectionView.indexPathsForVisibleItems.last?.row { // 这里表示要显示最后一个cell
//}
结语:
今天八月二十一号了。我们Team换了座位。也算的上是个惬意的位置,右边是很大飘窗,窗外是xx办事中心。好像是个欧式风格的建筑?想想两年前我坐在一个柱子旁边,有种被遗弃的感觉。