LoginSignup
1
3

More than 5 years have passed since last update.

[iOS][XCODE][UITableView]TableViewCellの高さを計算して調整する方法

Posted at

UITableViewCellの高さを自動調整するには、
UITableViewのrowHeightプロパティにUITableViewAutomaticDimensionを設定する方法がある。

だけど、この方法を使うにはTableView内の全てのセルにAutoLayoutが不足なく設定されていなければならない。
しかしレガシーなアプリだと、AutoLayoutが設定されていないものもあり、すべてのセルに対して設定し直すというのは面倒。
そんな時は、次のようにtableView:heightForRowAtメソッドで内容によって高さを調整したいセルの高さを計算して返す。

import UIKit

//各TableViewCellのIdentifier
private let topCellID = "topCellID"
private let middleCellID = "middleCellID"
private let bottomCellID = "bottomCellID"

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var mainTable: UITableView!

    static let cellIDs: [String] = [topCellID, middleCellID, bottomCellID]

    var cellTexts: [String: String] = [:]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        mainTable.delegate = self
        mainTable.dataSource = self

        cellTexts[topCellID] = self.reapeatChar(targetChar: "上", repeatNum: 100) + "終"
        cellTexts[middleCellID] = self.reapeatChar(targetChar: "中", repeatNum: 200) + "終"
        cellTexts[bottomCellID] = self.reapeatChar(targetChar: "下", repeatNum: 300) + "終"
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // 行数
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return ViewController.cellIDs.count
    }

    // セルの高さ
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let cellId: String = ViewController.cellIDs[indexPath.row]
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellId)!

        if [topCellID, middleCellID, bottomCellID].contains(cellId) {
            return self.getCellHeight(tableView: tableView, text: self.cellTexts[cellId]!)
        }

        return cell.bounds.height
    }

    // セルの中身
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellId: String = ViewController.cellIDs[indexPath.row]
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellId)!

        if cellId == topCellID {
            let label = cell.viewWithTag(100) as! UILabel
            label.text = cellTexts[cellId]
        } else if cellId == middleCellID {
            let label = cell.viewWithTag(100) as! UILabel
            label.text = cellTexts[cellId]
        } else if cellId == bottomCellID {
            let label = cell.viewWithTag(100) as! UILabel
            label.text = cellTexts[cellId]
        }

        return cell
    }

    // セクション数
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    // セルの高さを返す
    private func getCellHeight(tableView: UITableView, text: String) -> CGFloat {

        let maxMessageLabelWidth: CGFloat = UIScreen.main.bounds.size.width
        let messageLabelHeight: CGFloat = self.getLabelSize(text: text, font: UIFont.systemFont(ofSize: 13.0), width: maxMessageLabelWidth, height: CGFloat.greatestFiniteMagnitude).height

        return messageLabelHeight + 16 //ラベルの上下には間隔が空くので16ptほど余分に高さを設定
    }

    // 高さと幅を計算するメソッド
    private func getLabelSize(text: String, font: UIFont, width: CGFloat, height: CGFloat) -> CGSize {
        let maxSize: CGSize = CGSize(width: width, height: height)
        let attr = [NSFontAttributeName: font]

        let size: CGSize = text.boundingRect(with: maxSize,
                                             options: [NSStringDrawingOptions.usesLineFragmentOrigin, NSStringDrawingOptions.truncatesLastVisibleLine],
                                             attributes: attr,
                                             context: nil).size
        return size
    }

    private func reapeatChar(targetChar: String, repeatNum: Int) -> String {
        var resStr: String = ""
        for _ in 1 ... repeatNum {
            resStr += targetChar
        }
        return resStr
    }
}
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3