Edited at

iOS10 の UITableViewの高さが変わった時のアニメーションについて

More than 1 year has passed since last update.


はじめに

こんにちは

タップするなど、高さがアニメーションして変わるTableViewが

iOS 9以前 と iOS 10.0 で動きが少し異なってしまい、調べていたら見つけたので

まとめてみたいと思います。

至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。


デモ


実行時(iOS 9以前)

7-3-1.gif


実行時(iOS 10)

8.gif

(見づらくてごめんなさい...)

iOS 10だと高さを変えた時にセル同士のラベルが重なっているように見えてしまいます。


TableViewをreloadするタイミングでアニメーションを設定すると良い?

アニメーションして高さが変わるTableViewのセルをリロードする時は

tableView.reloadData()

ではなく

tableView.beginUpdates()

//データを変更する処理など
tableView.endUpdates()

とメソッドで挟むように記述します。そのTableViewに乗っているCellを


CustomTableViewCell.swift

override func layoutSubviews() {

super.layoutSubviews()
if #available(iOS 10, *) {
UIView.animate(withDuration: 0.3) { self.contentView.layoutIfNeeded() }
}
}

のようにアニメーションを設定するとiOS 9以前の動きにできるみたいです。


もう1つの方法とその違い

また、以下のように設定する方法もあるみたいです。

UIView.animate(withDuration: 0.3) {

self.tableView.beginUpdates()
//セルのデータを変更する処理など
self.tableView.endUpdates()
cell.layoutIfNeeded()
}


実行時(iOS 10)(わかりやすく色を付けてみました)

color.gif

この記述だとセルが小さく戻る時に、

他のセルの上を股がるようにアニメーションしてしまいます。

(緑・茶色のセルが画面に表示される際に水色の下から順に表示されるようなアニメーション)


サンプルコード

一応gifのコードを貼っておきたいと思います。


CustomTableViewCell.swift

import UIKit

class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel!

var isOpen = false

override func awakeFromNib() {
super.awakeFromNib()
}

override func layoutSubviews() {
super.layoutSubviews()
if #available(iOS 10, *) {
UIView.animate(withDuration: 0.3) { self.contentView.layoutIfNeeded() }
}
}
}



MainViewController.swift

import UIKit

class MainViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!

var cellTexts = ["AAA","BBB","CCC","DDD","EEE"]
var openHeights: [CGFloat] = [308,132,132,132,132]
var colors: [UIColor] = [UIColor.red,UIColor.blue,UIColor.cyan,UIColor.green,UIColor.brown]
var isOpens = [false,false,false,false,false]

override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
let nib = UINib(nibName: "CustomTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "CustomTableViewCell")
}
}

extension MainViewController: UITableViewDataSource {
//テーブルの行ごとのセルを返却するメソッド
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for:indexPath) as! CustomTableViewCell
cell.selectionStyle = .none
cell.label.text = cellTexts[indexPath.row]
cell.isOpen = isOpens[indexPath.row]
cell.backgroundColor = colors[indexPath.row]
return cell
}

//テーブルの行数を返却するメソッド
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellTexts.count
}
}

extension MainViewController: UITableViewDelegate {
//セルを選択した時の処理
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell
UIView.animate(withDuration: 0.3) {
self.tableView.beginUpdates()
if cell.isOpen{
cell.isOpen = false
self.isOpens[indexPath.row] = false
}else{
cell.isOpen = true
self.isOpens[indexPath.row] = true
}
self.tableView.endUpdates()
cell.layoutIfNeeded()
}

}

// テーブルセルの高さを返します
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return isOpens[indexPath.row] ? openHeights[indexPath.row] : 44
}
}



参考にさせていただいたページ

このiOS 10のUITableViewのアニメーションについて


スタック・オーバーフロー


アニメーションするUITableViewについて


しめ鯖日記 さん


バージョンチェックについて


不満足こそが、極上を生む。さん


見て頂いてありがとうございます。