web-dev-qa-db-de.com

Dynamisches Höhenproblem für UITableView-Zellen (Swift)

In die Tabellenzellenbezeichnungen wird dynamischer Text mit variabler Länge eingefügt. Um die Höhe der Tableview-Zellen dynamisch zu dimensionieren, habe ich in viewDidLoad() Folgendes implementiert:

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

Dies funktioniert gut für die Zellen, zu denen noch gescrollt werden muss (da UITableViewAutomaticDimention beim Scrollen zur Zelle aufgerufen wird), nicht jedoch für die Zellen, die beim Laden der Tabelle mit Daten zunächst auf dem Bildschirm dargestellt werden.

Ich habe versucht, die Daten einfach neu zu laden (wie in vielen anderen Ressourcen vorgeschlagen):

self.tableView.reloadData()

in viewDidAppear() und viewWillAppear() und es war ohne Erfolg. Ich bin verloren. Weiß jemand, wie Xcode die dynamische Höhe der ursprünglich auf dem Bildschirm geladenen Zellen rendern soll? 

Bitte lassen Sie mich wissen, ob es eine bessere alternative Methode gibt.

48
simplexity

Versuche dies:

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

EDIT

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
}

Definieren Sie oben beide Methoden.
Es löst das Problem.

PS: Damit dies funktioniert, sind obere und untere Einschränkungen erforderlich.

Hier ist ein Beispiel

88
iDhaval

Benutze das:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

und verwenden Sie nicht: heightForRowAtIndexPath Delegatfunktion

Legen Sie im Storyboard auch nicht die Höhe des Etiketts fest, das eine große Datenmenge enthält. Geben Sie top, bottom, leading, trailing-Einschränkungen. 

29
ami rt

Swift 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

UND !!! In Storyboard: Sie MÜSSEN TOP & BOTTOM-Einschränkungen für Ihr Label festlegen Nichts anderes.

12

Dieser seltsame Fehler wurde durch Interface Builder-Parameter behoben, da die anderen Antworten das Problem nicht lösten.

Alles, was ich tat, war, die Standardbeschriftungsgröße größer zu machen, als der Inhalt möglicherweise sein könnte, und sie auch in der estimatedRowHeight-Höhe wiedergeben zu lassen. Zuvor habe ich die voreingestellte Zeilenhöhe im Interface Builder auf 88px gesetzt und dies in meinem Controller viewDidLoad() so wiedergegeben:

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

Das hat aber nicht geklappt. So wurde mir klar, dass der Inhalt nie größer werden würde als 100px. Deshalb habe ich die Standardhöhe der Zellen auf 108px (größer als der potenzielle Inhalt) festgelegt und dies im Controller viewDidLoad() so wiedergegeben:

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

Dies erlaubte tatsächlich den Code zusammenschrumpfen die anfänglichen Etiketten auf die richtige Größe. Mit anderen Worten, es dehnte sich nie zu einer größeren Größe aus, sondern konnte immer kleiner werden ... Außerdem wurde in self.tableView.reloadData() keine zusätzliche Funktion viewWillAppear() benötigt.

Ich weiß, dass dies nicht sehr variable Inhaltsgrößen abdeckt, aber dies funktionierte in meiner Situation, in der der Inhalt eine maximal mögliche Zeichenanzahl hatte.

Nicht sicher, ob dies ein Fehler in Swift oder Interface Builder ist, aber es funktioniert wie ein Zauber. Versuche es!

10
simplexity

Legen Sie die automatische Bemaßung für Zeilenhöhe und geschätzte Zeilenhöhe fest und stellen Sie folgende Schritte sicher:

@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
}

Zum Beispiel: Wenn Sie ein Label in Ihrer UITableviewCell haben, dann

  • Setze Zeilenanzahl = 0 (& Zeilenumbruchmodus = Ende abschneiden)
  • Legen Sie alle Einschränkungen (oben, unten, rechts links) in Bezug auf den Superview-/Zellencontainer fest.
  • Optional : Legen Sie die Mindesthöhe für die Beschriftung fest, wenn Sie möchten, dass der vertikale Mindestbereich durch die Beschriftung abgedeckt wird, auch wenn keine Daten vorhanden sind.

Hier ist ein Beispieletikett mit dynamischen Höhenbeschränkungen.

enter image description here

7
Krunal

Für die dynamische Größenänderung von UITableView waren zwei Dinge erforderlich 

  1. Festlegen der rechten Einschränkung Ihrer Ansicht in der Tabellenzellenzelle (meistens beinhaltet es, dass Sie Ihrer Ansicht die richtigen oberen, unteren und unteren Randbedingungen geben)
  2. Aufrufen dieser Eigenschaften von TableView in viewDidLoad ()

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

Dies ist ein wunderbares Tutorial zum Selbstanpassen (dynamische Tabellenzellen) in Swift 3.

7
osama

Für Swift 3 können Sie Folgendes verwenden:

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

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

Versuchen

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

Ich hatte das gleiche Problem und es funktioniert für mich.

2
Maickell Vilela

Stellen Sie sicher, dass Sie die folgenden Änderungen vornehmen, damit UITableViewCell automatisch skaliert werden kann:

  • Im Storyboard sollte Ihr UITableView nur dynamische Prototypzellen enthalten (statische Zellen sollten nicht verwendet werden), andernfalls funktioniert Autoresizing nicht. 
  • In Storyboard hat Ihr UITableViewCell UILabel für alle 4 Einschränkungen konfiguriert, dh obere, untere, Führende und nachfolgende Einschränkungen.
  • Im Storyboard sollte die Anzahl der Zeilen von UITableViewCell UILabel 0 sein
  • In der ViewDidLoad-Funktion Ihres UIViewControllers unter den UITableView-Eigenschaften festgelegt:

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

In meinem Fall - Im Storyboard hatte ich zwei Beschriftungen wie im Bild unten, bei beiden Beschriftungen wurden die gewünschten Breitenwerte eingestellt, bevor ich sie gleich machte. Sobald Sie die Auswahl aufheben, wird es automatisch, und wie üblich sollten die folgenden Dinge wie Charme funktionieren.

1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.

enter image description here

1
virtplay

Ich wurde von Ihrer Lösung inspiriert und versuchte es auf andere Weise.

Bitte versuchen Sie, tableView.reloadData() zu viewDidAppear() hinzuzufügen.

Das funktioniert für mich.

Ich denke, die Dinge hinter dem Scrollen sind "die gleichen" wie reloadData. Wenn Sie den Bildschirm scrollen, ist es so, als würde reloadData() aufgerufen, wenn viewDidAppear.

Wenn dies funktioniert, antworten Sie bitte auf diese Antwort, damit ich mir dieser Lösung sicher sein kann.

1
Kang Cheng

Für Swift habe ich diese Antwort auch in iOS 9.0 und iOS 11 überprüft (Xcode 9.3)

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

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

Hier müssen Sie obere, untere, rechte und linke Nebenbedingungen hinzufügen

1
iOS

Ich benutze diese

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

    return 100
}
1
gms

Leider bin ich mir nicht sicher, was mir gefehlt hat. Die oben genannten Methoden funktionieren bei mir nicht, um die Höhe der XIB-Zelle zu ermitteln, oder lassen Sie layoutifneeded () oder UITableView.automaticDimension die Höhenberechnung durchführen. Ich habe 3 bis 4 Nächte gesucht und versucht, aber keine Antwort gefunden. Einige Antworten hier oder in einem anderen Beitrag gaben mir jedoch Hinweise zur Problemumgehung. Es ist eine dumme Methode, aber es funktioniert. Fügen Sie einfach alle Ihre Zellen zu einem Array hinzu. Stellen Sie dann den Ausgang jeder Ihrer Höhenbeschränkungen im xib-Storyboard ein. Addieren Sie sie schließlich in der heightForRowAt-Methode. Es ist einfach unkompliziert, wenn Sie mit diesen APIs nicht vertraut sind.

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

Zusätzlich zu dem, was andere gesagt haben, 

SETZEN SIE DIE BESCHRÄNKUNGEN IHRES LABELS IN VERBINDUNG MIT DEM SUPERVIEW!

Anstatt die Einschränkungen Ihres Labels relativ zu anderen Dingen zu setzen, beschränken Sie es auf die Inhaltsansicht der Tabellensichtzelle.

Stellen Sie dann sicher, dass die Höhe Ihres Labels auf mindestens 0 eingestellt ist und dass die Anzahl der Zeilen auf 0 gesetzt ist. 

Dann in ViewDidLoad hinzufügen:

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

0
Will Said

Für 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
}

Glückliche Kodierung :)

0
Ariven Nadar

Wenn ich ein statisches UITableView verwende, setze ich alle Werte in den UILabels und rufe dann tableView.reloadData() auf.

0
Zandor Smith
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

Und vergessen Sie nicht, für label button constraints hinzuzufügen

0
Vineesh TP

Für Ziel C ist dies eine meiner schönen Lösungen. es hat für mich gearbeitet.

- (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;
}

Wir müssen diese 2 Änderungen anwenden.

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

2)return UITableViewAutomaticDimension;
0
iOS

Anfangs hatte ich auch dieses Problem, ich hatte mein Problem mit diesem Code gelöst. Versuchen Sie, die Verwendung von self.tableView.reloadData() anstelle dieses Codes für die dynamische Höhe zu vermeiden

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

Dies ist einfach, wenn Sie zwei Dinge tun:

  1. einstellen der automatischen Höhe

    tableView.rowHeight = UITableView.automaticDimension

  2. erstellen aller TableViewCells mit FULL Einschränkungen von oben nach unten. Das letzte Element ** MUSS ** einen Abstand von unten definieren, um die Zelle zu beenden.

Die Layout-Engine kann also die Zellenhöhe berechnen und den Wert korrekt anwenden.

0
Karsten

Sie sollten nur alle Einschränkungen fürOBEN,UNTENundH&OUML;HEfür jedes Objekt in Zellansichtansichten festlegen und Vorhandene/- mittlere Y - Position entfernen, falls vorhanden . Denn wo Sie dies nicht getan haben, fügt Artefakte andere Ansichten hinzu.

0
Gennady Dmitrik