Swift - 实现UICollectionView分组头悬停效果(方法2:使用iOS9新特性)
而从 iOS9 起,UICollectionViewFlowLayout(默认的流式布局)新增了两个属性:
- sectionHeadersPinToVisibleBounds:是否将分组头钉在可视区域
- sectionFootersPinToVisibleBounds:是否将分组尾钉在可视区域
有了这两个属性,我们不再需要自己实现相关的布局类,就可以实现分组头、分组尾的悬停效果。
(虽然这两个属性很方便,但有时为了实现一些特殊需求,比如想要用户滚动视图的时候逐渐淡化分组头直至消失,还是需要通过自定义布局来实现。)
1,效果图
可以看到,随着我滚动单元格视图,分组头都是固定在对应分组可视区域的顶部,不会跟着移动。
2,样例代码
(1)自定义单元格类:MyCollectionViewCell.swift(创建的时候生成对应的 xib 文件)
import UIKit //自定义的Collection View单元格 class MyCollectionViewCell: UICollectionViewCell { //用于显示书籍封面图片 @IBOutlet weak var imageView: UIImageView! override func awakeFromNib() { super.awakeFromNib() } }
(2)自定义分组头:MySectionHeader.swift(创建的时候生成对应的 xib 文件)
import UIKit //自定义的Collection View分组头 class MySectionHeader: UICollectionReusableView { //用于显示分组标题 @IBOutlet weak var titleLabel: UILabel! override func awakeFromNib() { super.awakeFromNib() } }
(3)使用样例:ViewController.swift
import UIKit //每月书籍 struct BookPreview { var title:String var images:[String] } class ViewController: UIViewController { //重用的单元格和分区头的Identifier let CellIdentifier = "myCell" let HeaderIdentifier = "myHeader" //所有书籍数据 let books = [ BookPreview(title: "五月新书", images: ["0.jpg", "1.jpg","2.jpg", "3.jpg", "4.jpg","5.jpg","6.jpg"]), BookPreview(title: "六月新书", images: ["7.jpg", "8.jpg", "9.jpg"]), BookPreview(title: "七月新书", images: ["10.jpg", "11.jpg", "12.jpg", "13.jpg"]) ] override func viewDidLoad() { super.viewDidLoad() //初始化Collection View initCollectionView() } private func initCollectionView() { //初始化flow布局 let layout = UICollectionViewFlowLayout() //分组头悬停 layout.sectionHeadersPinToVisibleBounds = true //初始化Collection View let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout) //Collection View代理设置 collectionView.delegate = self collectionView.dataSource = self collectionView.backgroundColor = .white //注册重用的单元格 let cellXIB = UINib.init(nibName: "MyCollectionViewCell", bundle: Bundle.main) collectionView.register(cellXIB, forCellWithReuseIdentifier: CellIdentifier) //注册重用的分组头 let headerXIB = UINib.init(nibName: "MySectionHeader", bundle: Bundle.main) collectionView.register(headerXIB, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: HeaderIdentifier) //将Collection View添加到主视图中 view.addSubview(collectionView) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } } //Collection View数据源协议相关方法 extension ViewController: UICollectionViewDataSource { //获取分区数 func numberOfSections(in collectionView: UICollectionView) -> Int { return books.count } //获取每个分区里单元格数量 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return books[section].images.count } //返回每个单元格视图 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { //获取重用的单元格 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier, for: indexPath) as! MyCollectionViewCell //设置内部显示的图片 cell.imageView.image = UIImage(named: books[indexPath.section].images[indexPath.item]) return cell } //分区的header func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { // 获取重用的分组头 if let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: HeaderIdentifier, for: indexPath) as? MySectionHeader { //设置分组标题 header.titleLabel.text = books[indexPath.section].title return header } fatalError("获取重用视图失败!") } } //Collection View样式布局协议相关方法 extension ViewController: UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { //返回分组头大小 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { return CGSize(width: collectionView.bounds.width, height: 45.0) } //返回单元格大小 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let itemWidth = (collectionView.bounds.width - 5)/3 let itemHeight = itemWidth / 3 * 4 return CGSize(width: itemWidth, height: itemHeight) } //每个分组的内边距 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets.zero } //单元格的行间距 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 2.0 } //单元格横向的最小间距 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 0.0 } }源码下载:hangge_1600.zip
这个功能,很好,谢谢站长分享,不过 当有CollectionFooterView视图的时候,这个footer显示空白不加载,另外悬停到 footer处也有问题,请问怎么解决