何かと面倒なiOSの高さ問題。AutoLayoutを使う前提です。
共通
コードからでもStoryboardからでも構わないですが、UILabelのnumberOfLinesを0にします。
これで複数行表示できるようになります。
UITableViewCellの中で使う場合
Cellの高さを自動で計算させる方法があります。
SwiftでUITableViewCellの高さを動的に変更する
ポイントは、
1. UILabelと隣接するViewまでの上下距離に関する制約をつける
2. 以下の2行をviewDidLoad()あたりに書く
tableView.estimatedRowHeight = 適当な高さ
tableView.rowHeight = UITableViewAutomaticDimension
後は普通にUITableViewのDelegateとDataSourceを実装すればOK。
高さは勝手に計算されるので、heightForRowAtは不要です。
なんかスクロールがおかしい・・・?
上記だけでは、reloadData()とかscrollToRowAtIndexPath()をするとスクロールがおかしな位置に行ってしまうことがあります。
まだ生成されていないセルの高さを、estimatedRowHeightで設定した値で計算するためみたいです。
Autolayout で UITableViewCell の高さを設定すると reloadData 後にカクカクすることがある
正常にスクロールさせるには、estimatedHeightForRowAtで正確な高さを返します。
とは言え一度セルが生成されるまでは正確な高さはわからないので、最初はestimatedRowHeightを返します。
そして、willDisplayなどセルが生成された後で、実際のセルの高さを配列などに保存し、次からは保存した高さを返します。
private var cellHeightList: [IndexPath: CGFloat] = [:]
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = self.cellHeightList[indexPath] {
return height
}
else {
return tableView.estimatedRowHeight
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if !self.cellHeightList.keys.contains(indexPath) {
self.cellHeightList[indexPath] = cell.frame.size.height
}
}
UIViewで使う場合
子供の要素から適切なサイズを計算してくれる素敵なメソッドがあります。
UIKit - AutoLayoutを利用した高さ可変のTableHeaderViewをつくる
ポイントは、
1. UILabelと隣接するViewまでの上下距離に関する制約をつける
2. UILabelのtextに文字列を入れる
3. UIViewに対して、setNeedsLayout()とlayoutIfNeeded()を実行
4. systemLayoutSizeFitting(UILayoutFittingCompressedSize)でサイズを計算
5. 4で得られたサイズを使ってUIViewのframeなり制約なりを更新する
@IBOutlet weak var someViewHeightConstraint: NSLayoutConstraint!
private var someView: UIView!
private var label: UILabel!
func calcHeight() {
// 手順2
label.text = "複数行のテキスト"
// 手順3
someView.setNeedsLayout()
someView.layoutIfNeeded()
// 手順4
let size = someView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
// 手順5
someViewHeightConstraint.constant = size.height
}
これって・・・
そうですね、セルの高さ計算にも使えます。
テーブルビューのセル毎にピッタリの高さを計算する
でも最初に紹介した方法のほうが簡単です。
おわりに
昔は頑張って計算するしかなかったみたいなので、それに比べればだいぶ楽になりました。
それでもAutoLayoutとかテーブルの高さ計算の仕組みとかわかってないとうまくいかなかったりするので、メモ代わりに記事にしました。
リンク集みたいになってしまいましたが、誰かの役にたてば幸いです。