テーブルビューをセクションごとに開閉する

  • 36
    いいね
  • 0
    コメント

 やっはろー。セクションごとに開閉できるテーブルビューを実装したい、という話をします。

346 Production

こういう感じです。

開閉する

 セクション内の行数を増減するために、デリゲートメソッドで表示する行数を変えます。リロードするだけでアニメーションして便利。

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if self.openedSections.contains(section) {
        return self.items[section].members.count
    } else {
        return 0
    }
}

タップする

 タップを検知するために、セクションのヘッダにジェスチャを貼ります。タグにセクションの番号を入れると、タップしたセクションがすぐにわかって便利。

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let view = UITableViewHeaderFooterView()
    let gesture = UITapGestureRecognizer(target: self, action: #selector(self.tapSectionHeader(sender:)))
    view.addGestureRecognizer(gesture)
    view.tag = section

    return view
}
func tapSectionHeader(sender: UIGestureRecognizer) {
    if let section = sender.view?.tag {
        ...
    }
}

サンプルコード

 冒頭のあれです。

import UIKit

class ViewController: UITableViewController {
    private var openedSections = Set<Int>()
    private let items = [
        (type: "キュート", members: ["双葉", "緒方", "三村", "前川", "島村"]),
        (type: "クール", members: ["神崎", "多田", "アナ", "新田", "渋谷"]),
        (type: "パッション", members: ["諸星", "城ヶ崎", "赤城", "本田"]),
        (type: "ミシロ", members: ["美城"]),
    ]

    // コピペだけで動くように細工する
    required init?(coder aDecoder: NSCoder) {
        super.init(style: .plain)
    }

    // タップの邪魔なのでステータスバーを消す
    override var prefersStatusBarHidden: Bool {
        return true
    }

    func tapSectionHeader(sender: UIGestureRecognizer) {
        if let section = sender.view?.tag {
            if self.openedSections.contains(section) {
                self.openedSections.remove(section)
            } else {
                self.openedSections.insert(section)
            }

            self.tableView.reloadSections(IndexSet(integer: section), with: .fade)
        }
    }

    // MARK: Table view data source

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = self.items[indexPath.section].members[indexPath.row]

        return cell
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.openedSections.contains(section) {
            return self.items[section].members.count
        } else {
            return 0
        }
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return self.items.count
    }

    // MARK: Table view delegate

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return self.items[section].type
    }

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UITableViewHeaderFooterView()
        let gesture = UITapGestureRecognizer(target: self, action: #selector(self.tapSectionHeader(sender:)))
        view.addGestureRecognizer(gesture)
        view.tag = section

        return view
    }
}

楽しい!₍₍ (ง╹◡╹)ว ⁾⁾