LoginSignup
2
3

More than 3 years have passed since last update.

配置されたTextViewのテキストの量に応じてTableViewのCellの高さとTextViewの幅を動的に変更させる

Last updated at Posted at 2020-12-07

初めに

xibで作ったTableViewCellを想定しています

xibでのセルの作り方はこちらを参照ください
https://qiita.com/Secret-Base36/items/2a9a3989479559ba36ba

環境

Xcode 12.2

1. TextViewの設定

  • Scrolling Enableのチェックを外す

スクリーンショット 2020-12-07 20.35.06.png

2. TableViewのセルの高さの設定

TableViewのheightForRowAtメソッドで可変に設定

  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //セルの推定最低高さ(不要?)
    secondTableView.estimatedRowHeight = 50
    //セルの高さを可変に設定
    return UITableView.automaticDimension
  }

estimatedRowHeight(セルの推定高さ)は記述しなくても結果は変わらなかった

ここまでの結果

スクリーンショット 2020-12-07 21.28.56.png

文字量によってセルの高さが変わる様になった!

微調整

上の図の様に最小高さの場合に、他のUIが重なるなど影響が出る場合は、制約で調整すると良い

スクリーンショット 2020-12-07 21.31.44.png

スクリーンショット 2020-12-07 21.39.35.png

ここまでで高さを動的に変更させるまでは終わり

ここからは、幅も動的に変更させる方法

3.textからViewの幅を計算する

TableViewCellのクラスにメソッドを追加する

SecondTableViewCell.swift
//セルのTextViewの幅の計算
  private func estimateFrameForTextView(text: String) -> CGRect{
    //最大値
    let size = CGSize(width: 200, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)

    return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)], context: nil)
    //systemFont(ofSize)にはTextViewに設定したサイズを設定する
  }

4.Textを受ける変数を定義して、幅の制約をCellのクラスとOutlet接続

スクリーンショット 2020-12-13 15.44.51.png
接続名は"textViewWidthConstraint"としました

5.作成したCell側の変数にTextを渡す

TableViewのcellForRowAtからCellのmsgText変数にテキストを格納

SecondViewController.swift
  //セルの内容
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = secondTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! SecondTableViewCell
    cell.backgroundColor = .lightText
    //cell.textView.text = textArray[indexPath.row]

    //★★★ Cellクラスの変数に格納 (ここで渡している)
    cell.msgText = textArray[indexPath.row]

    return cell

6.Cellクラス側で幅を計算させて、TextViewの幅を変更するコードを書く

受け取ったテキストをもとに、estimateFrameForTextViewメソッドで幅を計算させて、その幅でTextViewの幅を変更する

SecondTableViewCell.swift
//ViewControllerからテキストを受け取る変数
  var msgText :String? {
    //didSetで値の変更後(計算後)に通知
    didSet {
      //nilチェック
      guard let text = msgText else { return }
      //幅計算メソッドで幅を計算する + 10は幅に余裕を持たせる為(無いと不用意な改行が入ることも)
      let width = estimateFrameForTextView(text: text).width + 10

      textViewWidthConstraint.constant = width
      textView.text = text
    }
  }

以上です

スクリーンショット 2020-12-13 16.32.27.png

最後に

情報が間違っているなどありましたら、お手数ですがご指摘いただけると幸いです。
下に全コードを載せておきます

SecondTableViewCell.swift
import UIKit

class SecondTableViewCell :UITableViewCell{

  //ViewControllerからテキストを受け取る変数
  var msgText :String? {
    //didSetで値の変更後(計算後)に通知
    didSet {
      //nilチェック
      guard let text = msgText else { return }
      //幅計算メソッドで幅を計算する + 10は幅に余裕を持たせる為(無いと不用意な改行が入ることも)
      let width = estimateFrameForTextView(text: text).width + 10

      textViewWidthConstraint.constant = width
      textView.text = text
    }
  }


  //★★★UIとの接続
  @IBOutlet weak var cellImageView: UIImageView!
  @IBOutlet weak var textView: UITextView!


  @IBOutlet weak var textViewWidthConstraint: NSLayoutConstraint!


  override func awakeFromNib() {
    super.awakeFromNib()

    //CellのUIのプロパティー変更
    cellImageView.layer.cornerRadius = 25

  }

  override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

  }

  //セルのTextViewの幅の計算
  private func estimateFrameForTextView(text: String) -> CGRect{
    //最大値
    let size = CGSize(width: 200, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)


    return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)], context: nil)
    //systemFont(ofSize)にはTextViewに設定したサイズを設定する
  }
}

SecondViewController.swift
import UIKit

class SecondViewController : UIViewController{


  private let cellId = "cellId"


  var textArray = ["あいうえお",
                   "あいうえお\nかきくけこ",
                   "あいうえおかきくけこさしすせそ",
                   "あいう\nえおかきくけこさしすせそ\nたちつてと"]


  @IBOutlet weak var secondTableView: UITableView!
  override func viewDidLoad() {
    super.viewDidLoad()




    secondTableView.delegate = self
    secondTableView.dataSource = self

    //セルの登録(Xibファイル名:SecondViewTableViewCell.xibの場合)
    secondTableView.register(UINib(nibName: "SecondViewTableViewCell", bundle: nil), forCellReuseIdentifier: cellId)



  }
}

extension SecondViewController :UITableViewDelegate,UITableViewDataSource{

  //セルの高さ
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //Cellの高さを可変にする
    return UITableView.automaticDimension
  }
  //セルの個数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return textArray.count
  }
  //セルの内容
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = secondTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! SecondTableViewCell
    cell.backgroundColor = .lightText
    //cell.textView.text = textArray[indexPath.row]

    //Cellクラスの変数に格納
    cell.msgText = textArray[indexPath.row]

    return cell
  }
}
2
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
2
3