web-dev-qa-db-ja.com

UITableViewセルの動的な高さの問題(Swift)

可変長の動的テキストがTableviewセルラベルに挿入されています。 TableViewセルの高さを動的にサイズ変更するために、viewDidLoad()に実装しました:

self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension

これは、まだスクロールされていないセル(UITableViewAutomaticDimentionがセルへのスクロール時に呼び出されるため)に対してはうまく機能しますが、データをテーブルにロードするときに最初に画面上にレンダリングされるセルに対しては機能しません。

私は単純にデータをリロードしようとしました(他の多くのリソースで提案されているように):

self.tableView.reloadData()

viewDidAppear()viewWillAppear()の両方で、役に立たなかった。私は迷っています..画面に最初に読み込まれたセルの動的な高さをXcodeでレンダリングする方法を知っている人はいますか?

より良い代替方法があれば、教えてください。

57
simplexity

これを試して:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

編集

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Swift 4

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Swift 4.2

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

上記の両方のメソッドを定義します。
問題を解決します。

PS:これが機能するためには、上下の制約が必要です。

ここに例があります

95
iDhaval

これを使って:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

使用しない:heightForRowAtIndexPathデリゲート関数

また、ストーリーボードでは、大量のデータを含むラベルの高さを設定しないでください。 top, bottom, leading, trailing制約を付けます。

30
ami rt

スイフト3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

そして!!! storyBoardの場合:ラベルの上部および下部の制約を設定する必要があります。他に何もありません。

12

この奇妙なバグは、他の回答では問題が解決されなかったため、Interface Builderのパラメーターで解決されました。

私がしたことは、デフォルトのラベルサイズをコンテンツよりも大きくすることができ、estimatedRowHeightの高さにも反映させることでした。以前は、Interface Builderでデフォルトの行の高さを88pxに設定し、コントローラーviewDidLoad()のように反映していました。

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

しかし、それはうまくいきませんでした。 そのため、コンテンツが100pxより大きくなることはないことに気付いたので、デフォルトのセルの高さを108px(潜在的なコンテンツよりも大きい)に設定し、コントローラーviewDidLoad()にそのように反映しました。

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0

これにより、実際にコードは 縮小する 初期ラベルを正しいサイズに。言い換えると、それは決して大きなサイズに拡張することはありませんでしたが、常に縮小することができました...また、self.tableView.reloadData()に追加のviewWillAppear()は必要ありませんでした。

私はこれが非常に可変的なコンテンツサイズをカバーしていないことを知っていますが、これはコンテンツが可能な最大文字数を持っている私の状況で機能しました。

これがSwiftまたはInterface Builderのバグかどうかはわかりませんが、それは魅力のように機能します。試してみる!

10
simplexity

行の高さと推定される行の高さの自動寸法を設定し、次の手順を確認します。

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

例:UITableviewCellにラベルがある場合、

  • 行数を0に設定(&改行モード=末尾を切り捨て)
  • スーパービュー/セルコンテナに関してすべての制約(上、下、右左)を設定します。
  • オプション:データがない場合でも、ラベルで覆われる最小の垂直領域が必要な場合は、ラベルの最小高さを設定します。

これは、動的な高さの制約のあるラベルの例です。

enter image description here

7
Krunal

UITableViewの動的サイズ変更セルには2つの項目が必要でした

  1. テーブルビューセル内でのビューの適切な制約の設定(ほとんどの場合、ビューに適切なtop、bottom、traling制約を与えることを含みます)
  2. ViewDidLoad()でTableViewのこれらのプロパティを呼び出す

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

This はSwift 3で書かれた自己サイズ変更(動的なテーブルビューセル)に関するすばらしいチュートリアルです。

7
osama

Swift 3の場合、次を使用できます。

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}
4
Ahmed Lotfy

Swift 4.2の場合

@IBOutlet weak var tableVw: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set self as tableView delegate
    tableVw.delegate = self

    tableVw.rowHeight = UITableView.automaticDimension
    tableVw.estimatedRowHeight = UITableView.automaticDimension
}

// UITableViewDelegate Method 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return UITableView.automaticDimension
}

ハッピーコーディング:)

2
Ariven Nadar

試して

override func viewWillAppear(animated: Bool) {
    self.tableView.layoutSubviews()
}

私は同じ問題を抱えていましたが、それは私にとってはうまくいきます。

2
Maickell Vilela

UITableViewCellの自動サイズ変更を機能させるには、これらの変更を行っていることを確認してください。

  • ストーリーボードでは、UITableViewにダイナミックプロトタイプセルのみを含める必要があります(静的セルを使用しないでください)。そうしないと、自動サイズ変更は機能しません。
  • ストーリーボードでは、UITableViewCellのUILabelは、上部、下部、先頭および末尾の制約である4つの制約すべてに対して構成されています。
  • ストーリーボードでは、UITableViewCellのUILabelの行数は0でなければなりません
  • UITableViewのプロパティの下に設定されたUIViewControllerのviewDidLoad関数で:

    self.tableView.estimatedRowHeight = <minimum cell height> 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    
2
Anshul Sharma

私はあなたのソリューションに触発され、別の方法を試しました。

tableView.reloadData()viewDidAppear()に追加してください。

これは私のために動作します。

スクロールの背後にあるものはreloadDataと「同じ」だと思います。画面をスクロールすることは、viewDidAppearのときにreloadData()を呼び出すようなものです。

これが機能する場合、この解決策を確信できるように、plzがこの回答を返信します。

1
Kang Cheng

Swiftについては、iOS 9.0およびiOS 11でもこの回答を確認しました(Xcode 9.3)

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

ここに追加する必要があります上、下、右および左の制約

1
iOS

私はこれらを使用します

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return 100
}
1
gms

残念ながら、何が欠けていたのかわかりません。上記のメソッドは、xibセルの高さを取得したり、layoutifneeded()またはUITableView.automaticDimensionに高さの計算をさせたりするためには機能しません。私は3〜4泊探してみましたが、答えが見つかりませんでした。ここまたは別の投稿のいくつかの回答は、回避策のヒントを与えてくれました。これは愚かな方法ですが、動作します。すべてのセルを配列に追加するだけです。次に、xibストーリーボードで各高さ制約のアウトレットを設定します。最後に、それらをheightForRowAtメソッドに追加します。これらのAPIに慣れていない場合は、簡単です。

Swift 4.2

CustomCell.Swift

@IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
@IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
@IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!

@IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
@IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!

MyTableViewVC.Swift

.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell

.
.
myCustomCells.append(cell)
return cell

}


override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant

  return totalHeight + 40 //some magic number


}
1
William Tong

他の人が言ったことに加えて、

スーパービューに関連してラベルの制約を設定してください!

そのため、ラベルの制約をその周りの他のものに対して相対的に配置する代わりに、テーブルビューセルのコンテンツビューに制約します。

次に、ラベルの高さが0以上に設定され、行数が0に設定されていることを確認します。

次に、ViewDidLoadで以下を追加します。

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

0
Will Said

Objective Cでは、これは私の素敵なソリューションの1つです。それは私のために働いた。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

これらの2つの変更を適用する必要があります。

1)cell.textLabel.numberOfLines = 0;
  cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;

2)return UITableViewAutomaticDimension;
0
iOS

私も最初にこの問題を抱えていましたが、このコードから問題を解決しましたが、動的な高さにはこのコードの代わりにself.tableView.reloadData()の使用を避けてください

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
0
ShujatAli

セルビュー/ビューの各オブジェクトに対してTOPBOTTOMおよびHEIGHTのすべての制約を設定し、exist 中央のY位置がある場合。これをしなかった場所では、別のビューにアーティファクトが配置されるためです。

0
Gennady Dmitrik