Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
67
Help us understand the problem. What is going on with this article?
@akatsuki174

UICollectionViewのHeaderカスタマイズいろいろ

More than 3 years have passed since last update.

CollectionViewのHeaderを作る上でカスタマイズできる点についてまとめました。Swift4.0で書いています。

一応GitHubにコードを置いています。
https://github.com/akatsuki174/CollectionViewHeaderCustomizeSample

前提:Headerを表示するまで

UICollectionViewControllerを使って作る場合の一例がこちらになります。

storyboard

スクリーンショット 2017-11-12 0.03.14.png

cellはUICollectionViewControllerを用意した時にデフォルトでついていたものを使っています。headerはUICollectionReusableViewをObject Libraryから引っ張ってきて置いています。このheaderにはSectionHeaderというidentifierを振っています。

headerクラス

ラベル置いているだけなのでこれだけしか書いていません。

SectionHeader.swift
import UIKit

final class SectionHeader: UICollectionReusableView {
    @IBOutlet weak var sectionLabel: UILabel!
}

ViewControllerクラス

ViewController.swift
import UIKit

final class ViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

// MARK: datasorce, delegate

extension ViewController {
    override func collectionView(_ collectionView: UICollectionView,
                        cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        return cell
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 3
    }

    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "SectionHeader", for: indexPath) as? SectionHeader else {
            fatalError("Could not find proper header")
        }

        if kind == UICollectionElementKindSectionHeader {
            header.sectionLabel.text = "section \(indexPath.section)"
            return header
        }

        return UICollectionReusableView()
    }

}

この時点でのUI

スクリーンショット 2017-11-12 0.14.13.png

高さのカスタマイズ

全てのセクションヘッダを同じ高さにするのであればviewDidLoadを以下のようにすれば設定することができます。

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    guard let fl = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else { return }
    fl.headerReferenceSize = CGSize(width: self.view.bounds.width, height: 30)
}

スクリーンショット 2017-11-12 0.32.33.png

セクションによってヘッダの高さを変えたい場合はUICollectionViewDelegateFlowLayoutプロトコルを適用させた上で次のメソッドを追加すると高さを調節することができます。

ViewController.swift
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    if section == 1 {
        return CGSize(width: self.view.bounds.width, height: 50)
    } else {
        return CGSize(width: self.view.bounds.width, height: 30)
    }
}

ヘッダを表示しないセクションを作る

セクションによってセクションを出したい時、出したくない時があると思います。その時はさっき使ったメソッドを使って以下のように(0,0)を返します。

ViewController.swift
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    if section == 1 {
        return CGSize.zero
    } else {
        return CGSize(width: self.view.bounds.width, height: 30)
    }
}

スクリーンショット 2017-11-12 0.45.25.png

ヘッダを画面上部に固定する

上にスクロールさせた時にセクションヘッダを画面上部に固定する場合は以下のようにviewDidLoadにコードを追加します(これを書かずに今まで通りのコードを書いていれば画面上部に固定されません)。

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    guard let fl = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout else { return }
    fl.sectionHeadersPinToVisibleBounds = true
}

スクリーンショット 2017-11-12 1.00.09.png

xibで作ったヘッダを設定する

ヘッダはこんなふうに作りました。

スクリーンショット 2017-11-12 22.15.56.png

XibHeader.swift
final class XibHeader: UICollectionReusableView {

    @IBOutlet weak var sectionLabel: UILabel!

    static let identifier: String = "XibHeader"

    static func nib() -> UINib {
        return UINib(nibName: XibHeader.identifier, bundle: nil)
    }
}

上記ヘッダをセットするために、ViewController.swiftに以下のコードを足しています。

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()

    // 今まで書いた他の要素は省略

    collectionView?.register(XibHeader.nib(), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: XibHeader.identifier)
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    if kind == UICollectionElementKindSectionHeader {
        if indexPath.section == 0 || indexPath.section == 4 {
            guard let xibHeader = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: XibHeader.identifier, for: indexPath) as? XibHeader else {
                fatalError("Could not find proper header")
            }
            xibHeader.sectionLabel.text = "section \(indexPath.section)"
            return xibHeader
        } else {
            guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "SectionHeader", for: indexPath) as? SectionHeader else {
                fatalError("Could not find proper header")
            }
            header.sectionLabel.text = "section \(indexPath.section)"
            return header
        }
    }

    return UICollectionReusableView()
}

スクリーンショット 2017-11-12 22.13.44.png

67
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
akatsuki174
iOS→Androidエンジニアになりました。それなりに使える言語はSwift, Objective-C, Kotlin, Java。 UX, データ分析, グロースハック, デザイン, 自然言語処理にも興味あり。 1分野に固まらず、いろんな分野のことについて書いていこうと思います。
techtrain
プロのエンジニアを目指すU30(30歳以下)の方に現役エンジニアにメンタリングもらえるコミュニティです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
67
Help us understand the problem. What is going on with this article?