iOS8からのTableViewCellの高さ自動計算は、上スクロールした時にはうまく動かない件で、UITableViewCellの高さ自動計算でハマる場合がある事がわかりました。
これを回避するには、estimatedHeightを使わずに、真面目に高さ計算を行えば良いです。
Autolayoutが無い時代には、これをごりごりと計算していたのですが、UITableViewCellにAutolayoutを使う事で、かなり簡略化できたのでその記録を残します。
おおまかな流れ
- UITableViewDataSourceから参照できる所に、「表示する事の無い、高さ計算用のダミーセル」を用意します。
- tableView:heightForRowAtIndexPath: で、ダミーセルを使って高さ計算を行います。
- このときAutolayoutで計算ができるので、比較的楽です。
ソース
Objective-c
- (void)viewDidLoad {
[super viewDidLoad];
...
// estimatedRowHeightはガタガタの原因になるので使わない。
// self.tableView.estimatedRowHeight = 100;
// self.tableView.rowHeight = UITableViewAutomaticDimension;
// セルの高さを計算する用の、表示されないダミーのセルを用意する。
// ここでdequeueするのは、実際に表示するセルを使います。
self.dummyCell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell"];
}
/**
Autolayoutを使ったUITableViewCellの高さ計算
*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 高さ計算用のダミーのセルに、cellForRowAtIndexPathで行うのと
// 同じ設定をする。
[self setupCell:self.dummyCell atIndexPath:indexPath];
// 以下、サイズ計算用の処理です。
// ダミーセルそのものに操作しても、サイズ計算は行われないので、
// その内側にあるcontentViewに対して操作を行います。
// contentViewを再レイアウトする
[self.dummyCell.contentView setNeedsLayout];
[self.dummyCell.contentView layoutIfNeeded];
// contentViewの、Autolayoutに従った時のサイズを取得する
CGSize size = [self.dummyCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
// UITableViewの高さは、contentViewと「区切り線」を含んだ高さなので、
// 高さに区切り線分の高さを+1して返す
return size.height+1;
}
/** MyTableViewCellの設定処理 */
// MyTableViewCellへの設定処理が重たい場合は、
// 「高さ計算で必要な設定」と「高さ計算では不要な設定」に
// 分けたほうが良いかもしれません。
-(void)setupCell:(MyTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSUInteger num = (NSUInteger)[self.array[indexPath.row] integerValue];
cell.title.text = [self stringByLineNumber:num];
cell.backgroundColor = [self colorByNumber:num];
}
/** 実際に表示するCellを返す */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog( @"cellForRowAtIndexPath: row=%@",@(indexPath.row));
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"
forIndexPath:indexPath];
[self setupCell:cell atIndexPath:indexPath];
NSLog( @"cell=%@",cell);
return cell;
}
ソース https://github.com/taktamur/iOS8CellHeight/tree/after
おわりに
iOS8からUITableViewCellの高さ計算が自動になって、やぁ便利になったなぁと思いましたが、使い方によっては思った動作にならないようです。
ただ自動計算せずとも、heightForRowAtIndexPathの中で、「Autolayoutを使った高さ計算」ができれば、少しの手間で「高さの手動計算」ができるようです。
なので、高さの自動計算は、場面に応じての使い分けになるのでしょうね。