この記事について
AutoLayout 利用時の TableHeaderView Height 問題は多くの記事で取り上げられています。今回紹介するのは、その中でも実装難易度が低く、複雑性が低いものをサンプルを使いながら紹介します。
よってこの方法は解決スピードを重視したものとなりますので、ご理解ください。
- Swift 4.x
- Xcode 10.1
- iOS 12
高さ不確定の現状
import UIKit
class ViewController: UIViewController {
@IBOutlet private weak var tableView: UITableView!
private let headerView = UINib(nibName: "HeaderView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! HeaderView
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.tableHeaderView = headerView
}
}
// セルに関する処理は省略
このように TableHeaderView が正しく決まっておらず、レイアウトが崩れています(image/label/button の間隔が空きすぎてます)。
HeaderView 内で自動的に高さが決まるように設計しても、強制的に高さを変えられてしまう現象が発生しています。
解決方法
TableHeaderView 上のパーツを UIView 上に直置きするのではなく、1つ UIView を敷いてからその上に置くようにします。 BaseView
と定義している View のことです。そして、 BaseView
の上・左・右に対して制約をつけ、高さは中のパーツで決まるようにレイアウトします。
最後に、 BaseView
を IBOutlet でつなげて高さを外部から参照できるようにします。
class ViewController: UIViewController {
private let headerView = ...
...
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var frame = headerView.frame
frame.size.height = headerView.height
headerView.frame = frame
tableView.tableHeaderView = headerView
}
}
VC 側で高さを反映させて完了です。
問題解決
TableHeaderView の高さが強制的に決まってしまって、中のパーツで高さが決まってくれないのであれば、 UIView を1つ敷くことによってレイアウト計算を分け、AutoLayout によって決定した高さを TableHeaderView の高さに指定してしまえばいいじゃん!というアプローチでした。
最後に
素材として いらすとや を利用させていただきました。
実は、アプリ内に登場するカプセルフィギュアは本当に存在します(笑)。