Edited at

SwiftでTableViewCellの高さを動的に変える

More than 3 years have passed since last update.


はじめに

題名の通り、TableViewCellの高さを動的に変えてみます。

Self-Sizing Cellsとかいうやつです。

本記事のサンプルは、Xcode Ver7.3.1で実装しました。

iOS 8.0以降対象です。


Self-Sizing Cells??

セルの高さを自力で計算することなく動的な高さを持つセルを定義できるものです。


完成イメージ

name, commentを持つJSONからデータを取得します。

サンプルなので、表示する文字列はテキトーです。


profileSample.json

{

"profile": [
{"name": "AAA", "comment": "abcd123"},
{"name": "BBB", "comment": "あいう\nえお"},
{"name": "CCC", "comment": "こめんと\nコメント\nComment"},
{"name": "DDD", "comment": "01234\n56789\n98765\n43210"},
{"name": "EEE", "comment": "コメント\nコメント\nコメントコメント\nコメコメントントコメントコメント\nabc123"},
{"name": "FFF", "comment": ""},
{"name": "GGG", "comment": "abcd123"},
{"name": "HHH", "comment": "あいう\nえお"},
{"name": "III", "comment": "こめんと\nコメント\nComment"},
{"name": "JJJ", "comment": "01234\n56789\n98765\n43210"},
{"name": "KKK", "comment": "コメント\nコメント\nコメントコメント\nコメコメントントコメントコメント\nabc123"},
{"name": "LLL", "comment": ""},
{"name": "MMM", "comment": "コメント\nコメント\nコメント\nコメント\nコメント\nコメント"},
{"name": "NNN", "comment": "apple\niOS"},
{"name": "OOO", "comment": ""},
{"name": "PPP", "comment": "0\n11\n222\n3333\n44444\n555555\n6666666\n77777777\n888888888\n9999999999"},
]
}


このデータから、

名前(赤字)とコメント(黒字、複数行)を持つTableViewCellを作ります。

Simulator Screen Shot 2016.09.13 1.44.36.png


Cell内に配置したパーツに適切な制約をつける

本サンプルでは、Cell内にnameLabelとcommentLabelの二つ配置しています。

それぞれのラベルに適切な制約をつけてあげます。

nameLabelは、

上左右 Constrain 0

下 Constrain 8としました。

commentLabelは、

下左右 Constrain 0

上 Constrain 8としました。

(単に上下左右に制約をつけただけです。)

スクリーンショット 2016-09-13 1.58.54.png

また、commentLabelは複数行のテキストを表示するので

Linesに0を設定しておきます。

スクリーンショット 2016-09-17 21.03.07.png


TableViewの設定

estimatedRowHeightを設定する

tableView.estimatedRowHeight = 66

セルの高さを計算する直前までの高さになります。

(デフォルトの高さというイメージですかね。)

rowHeightにUITableViewAutomaticDimensionを設定する

tableView.rowHeight = UITableViewAutomaticDimension

estimatedRowHeightに任意の値を設定し、

rowHeightにUITableViewAutomaticDimensionを設定することで

動的にセルの高さを設定してくれるようになります。

その他の部分は、基本的なTableViewの実装と変わりません。

セルに表示するデータを取得したり、UITableViewDataSourceのデリゲートメソッドを定義したりするだけです。(基本的なTableViewの実装部分については説明を割愛させていただきます。)


作成したコード


ProfileViewController.swift

import UIKit

struct ProfileModel {
var name = ""
var comment = ""
}

struct ProfilesModel {
var profiles = [ProfileModel]()
}

class ProfileViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!
var profilesModel = ProfilesModel()

// MARK: Life Cycle
override func viewDidLoad() {
super.viewDidLoad()

tableView.estimatedRowHeight = 66
tableView.rowHeight = UITableViewAutomaticDimension

guard let jsonFilePath = NSBundle.mainBundle().pathForResource("profileSample", ofType: "json") else {
return
}
// JSONファイルのデータ整形し、profilesModelにセットする
JsonParser.parse(&profilesModel, jsonFilePath: jsonFilePath)

tableView.dataSource = self
}
}

// MARK: UITableViewDataSource
extension ProfileViewController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return profilesModel.profiles.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ProfileCell
cell.nameLabel.text = profilesModel.profiles[indexPath.row].name
cell.commentLabel.text = profilesModel.profiles[indexPath.row].comment
return cell
}
}



ProfileCell.swift

import UIKit

class ProfileCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var commentLabel: UILabel!

override func awakeFromNib() {
super.awakeFromNib()
nameLabel.textColor = UIColor.redColor()
}
}


JSONのparseしているのは、こちら。


JsonParser.swift

import UIKit

class JsonParser: NSObject {
/// JSONをparseする
class func parse(inout profilesModel: ProfilesModel, jsonFilePath: String) {
guard let data = NSData(contentsOfFile: jsonFilePath) else {
return
}

let dictionary:NSDictionary = try!
NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary

var profileModel = ProfileModel()

let profiles = dictionary["profile"] as! Array<NSDictionary>
for profile in profiles {
profileModel.name = profile["name"] as! String
profileModel.comment = profile["comment"] as! String

profilesModel.profiles.append(profileModel)
}

}
}



さいごに

TableViewCellの高さを動的に変えるのって大変なのかなーと思っていたけれど

ちゃんと整理してみたらとても簡単にできました。