6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift】CollectionViewでカスタムheaderとfooterを作成する

Posted at

#はじめに
今回はCollectionViewでheaderとfooterを扱う方法を紹介したいと思います。
以下のようなものを作ってみます。
ezgif.com-gif-maker (2).gif

#GitHub
以下のHeaderFooterCollectionViewに今回のリポジトリあります!

#実装
まず、真ん中の赤い正方形を作ります。
カスタムセルでXIBを作成してコードは以下のようにしてください。

MyCollectionViewCell
final class MyCollectionViewCell: UICollectionViewCell {
        
    static var toString: String {
        return String(describing: self)
    }
    static let id = MyCollectionViewCell.toString
    static func nib() -> UINib {
        return UINib(nibName: MyCollectionViewCell.toString, bundle: nil)
    }
    
    func configure() {
        backgroundColor = .red
    }
    
}

そして、ViewControllerviewDidLoad以下のように、UICollectionViewFlowLayoutを利用します。

ViewController
 let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        layout.itemSize = CGSize(width: self.view.frame.size.width / 2.2,
                                 height: self.view.frame.size.width / 2.2)
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView?.register(MyCollectionViewCell.nib(),
                                 forCellWithReuseIdentifier: MyCollectionViewCell.id)
        collectionView?.delegate = self
        collectionView?.dataSource = self
        collectionView?.backgroundColor = .white
        view.addSubview(collectionView!)
}

collectionViewの縦横のサイズを決めます。

ViewController
override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView?.frame = self.view.bounds
}

そして、delegateメソッドを以下のように書きます。

ViewController
extension ViewController: UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.id, for: indexPath) as! MyCollectionViewCell
        cell.configure()
        return cell
    }

}

これで真ん中に表示4つの赤い正方形が表示されたと思います。

次はheaderを作成していきます。
headerやfooterは以下のようなUICollectionReusableViewというものを使います。
スクリーンショット 2021-04-05 12.24.02.png

HeaderCollectionReusableView
final class HeaderCollectionReusableView: UICollectionReusableView {
    
    static var toString: String {
        return String(describing: self)
    }
    static let id = HeaderCollectionReusableView.toString
    
    private let label: UILabel = {
        let label = UILabel()
        label.text = "header"
        label.font = .systemFont(ofSize: 50)
        label.textAlignment = .center
        label.textColor = .white
        return label
    }()
    
    func configure() {
        backgroundColor = .green
        addSubview(label)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        label.frame = bounds
    }
    
}

そして、ViewControllerないで以下のように書いていきます。

cellを登録

ViewController
collectionView?.register(HeaderCollectionReusableView.self,
                                 forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                                 withReuseIdentifier: HeaderCollectionReusableView.id)

UICollectionViewDataSourceメソッド

ViewController
extension ViewController: UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader,
                                                                     withReuseIdentifier: HeaderCollectionReusableView.id,
                                                                     for: indexPath) as! HeaderCollectionReusableView
        header.configure()
        return header
    }
    
}

UICollectionViewDelegateFlowLayoutメソッド

ViewController
extension ViewController: UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: view.frame.size.width, height: 200)
    }

}

これで緑色のヘッダーがつかされたと思います。
青色のフッターも同じように作成します。

ただし、UICollectionViewDataSourcedequeueReusableSupplementaryViewを以下のように変更します。

ViewController
extension ViewController: UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        if kind == UICollectionView.elementKindSectionFooter {
            let footer = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter,
                                                                         withReuseIdentifier: FooterCollectionReusableView.id,
                                                                         for: indexPath) as! FooterCollectionReusableView
            footer.configure()
            return footer
        } else {
            let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader,
                                                                         withReuseIdentifier: HeaderCollectionReusableView.id,
                                                                         for: indexPath) as! HeaderCollectionReusableView
            header.configure()
            return header
        }
    }
    
}

最後に、以下のようにUICollectionViewDelegatenumberOfSectionsを追加すれば完成です。

ViewController
extension ViewController: UICollectionViewDelegate {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 5
    }
    
}

#解説
大切なところだけ解説します。
UICollectionReusableView
UICollectionReusableViewでカスタムヘッダーやフッターを作成します。
カスタムヘッダーの手順は以下の通りです。
1.カスタムヘッダーを用意する
2.viewDidLoadでカスタムヘッダーをregisterする
3.collectionView(viewForSupplementaryElementOfKind)
4.collectionView(referenceSizeForHeaderInSection)

viewForSupplementaryElementOfKindではヘッダーおよびフッターの設定をします。
referenceSizeForHeaderInSectionでは名前の通り、ヘッダーのサイズを決めます。

#おわりに
CollectionViewも奥が深いですね、、、

6
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?