やっはろー。セクションごとに開閉できるテーブルビュー、いわゆるアコーディオンメニューを実装したい、という話をします。
開閉する
セクションの開閉とは要するにセル数の増減のことなのでそのようにします。
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if openedSections.contains(section) {
return 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(sectionHeaderDidTap(_:)))
view.addGestureRecognizer(gesture)
view.tag = section
return view
}
@objc func sectionHeaderDidTap(_ sender: UIGestureRecognizer) {
if let section = sender.view?.tag {
...
}
}
サンプルコード
Playground で動くやつです。
import UIKit
import PlaygroundSupport
class ViewController: UITableViewController {
private let items = [
(type: "キュート", members: ["双葉", "緒方", "三村", "前川", "島村"]),
(type: "クール", members: ["神崎", "多田", "アナ", "新田", "渋谷"]),
(type: "パッション", members: ["諸星", "城ヶ崎", "赤城", "本田"]),
(type: "ミシロ", members: ["美城"]),
]
private var openedSections = Set<Int>()
@objc func sectionHeaderDidTap(_ sender: UIGestureRecognizer) {
if let section = sender.view?.tag {
if openedSections.contains(section) {
openedSections.remove(section)
} else {
openedSections.insert(section)
}
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 = items[indexPath.section].members[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if openedSections.contains(section) {
return items[section].members.count
} else {
return 0
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
// MARK: Table view delegate
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return items[section].type
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UITableViewHeaderFooterView()
let gesture = UITapGestureRecognizer(target: self, action: #selector(sectionHeaderDidTap(_:)))
view.addGestureRecognizer(gesture)
view.tag = section
return view
}
}
PlaygroundPage.current.liveView = ViewController()
楽しい!₍₍ (ง╹◡╹)ว ⁾⁾