Warum funktioniert UITableViewAutomaticDimension nicht?

75

Hallo, es gibt viele Fragen, die die dynamische Höhe UITableViewCellvon beantworten UITableView. Allerdings finde ich es komisch, als ich es getan habe.

Hier sind einige der Antworten:

hier und hier

Normalerweise würde dies die dynamische Höhe für die Zelle beantworten

tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension

aber in meinem Fall frage ich mich, dass diese Linie nichts tun wird.

my UITableViewwird angezeigt, nachdem Sie in der geteilten Ansicht auf die Registerkartenleiste geklickt haben. Ist das hilfreich?

Vielleicht fehlt mir etwas. Könnte mir jemand helfen, ich habe 2 Stunden damit verbracht, dumm zu sein.

Dies sind meine Einschränkungen für den Titel. Der Titel könnte lang sein, das Label jedoch nicht.

Geben Sie hier die Bildbeschreibung ein

und das ist meine Zelle

Geben Sie hier die Bildbeschreibung ein

CaffeineShots
quelle
2
Sie sollten das UITableViewCellAutolayout-Setup in xib / storyboard noch einmal überprüfen . Sie haben ein Problem dort 100%
Vitaliy Gozhenko
2
Ja, ich schreibe es um. Ich hoffe zu finden, was es verursacht
CaffeineShots
Wenn Sie Ihr xib / Storyboard dort posten, kann ich Ihnen dabei helfen
Vitaliy Gozhenko
Haben Sie Ihre Ansichtsbeschränkungen relativ zum oberen und unteren Rand Ihrer Zelleninhaltsansicht festgelegt?
Zell B.
soll ich nur einen Screenshot machen?
CaffeineShots

Antworten:

162

Damit UITableViewAutomaticDimension funktioniert, müssen Sie alle Einschränkungen für links, rechts, unten und oben in Bezug auf die Zellencontaineransicht festlegen. In Ihrem Fall müssen Sie den fehlenden unteren Bereich zur Überwachung der Einschränkung für die Beschriftung unter dem Titel hinzufügen

Zell B.
quelle
13
Beachten Sie, dass Sie wahrscheinlich die unteren Einschränkungen für einige Ansichten so einstellen müssen, dass sie> = und nicht nur = sind, damit sie mit der dynamischen Höhe der Zelle wachsen können. Das war der Trick für mich.
Ryan R
@khunshan Bist du sicher, dass du keine Größenklassen verwendest?
Zell B.
@ ZellB. Ja, du hast recht. Aufgrund einer Einschränkung fehlte die iPhone-Klasse. (Y)
Khunshan
Gotcha, danke.
Anees
27

Ich hatte Einschränkungen programmgesteuert hinzugefügt und sie versehentlich direkt zur Zelle hinzugefügt, dh nicht auf dem contentViewGrundstück. Hinzufügen der Einschränkungen, contentViewum es für mich zu lösen!

Augapfel
quelle
Ja, wir müssen klar wissen, welche Einschränkung wir für welche fehlende oder hinzugefügte Einschränkung verwenden. Dies kann zu Mehrdeutigkeiten oder nicht erfüllten Einschränkungen führen. Danke für die Antwort Mann!
CaffeineShots
Ich weiß, dass dies alt ist, aber ich denke nicht, dass dies der richtige Weg ist, dies zu tun. Wenn Sie die Einschränkungen nicht zur Inhaltsansicht hinzufügen. Die Ansicht wird verzerrt, wenn Sie einen Bearbeitungsstil für die Zelle wie Löschen öffnen oder die Zeile selbst verschieben.
Esko918
@ Esko918 Ich denke du liest seine Antwort falsch. Er gibt an, dass Sie dem Einschränkungen hinzufügen müssen contentView. Ich auch Einschränkungen der versehentlich hinzugefügt , UITableViewCellwenn es um den sein sollte UITableViewCell‚scontentView
Alan
Das ist, was ich gesagt habe. Wenn Sie der Inhaltsansicht keine Einschränkungen hinzufügen, wird die Ansicht verzerrt, wenn Sie einen Bearbeitungsstil wie Löschen oder Verschieben der Zeile auswählen. Sie sollten die Zellenansicht nicht direkt ändern, da UIKit das Zellenlayout ändert, wenn Sie den Bearbeitungsmodus aktivieren und die Zelle nach rechts verschoben wird. Sie sollten der Inhaltsansicht alle Unteransichten und Layouteinschränkungen hinzufügen. Nicht die Ansicht selbst
Esko918
24

Um die automatische Bemaßung für die Zeilenhöhe und die geschätzte Zeilenhöhe festzulegen, müssen Sie die folgenden Schritte ausführen, damit die automatische Bemaßung für das Layout der Zellen- / Zeilenhöhe wirksam wird.

  • Zuweisen und Implementieren von tableview dataSource und Delegieren
  • Zuweisen UITableViewAutomaticDimensionzu rowHeight & geschätzteRowHeight
  • Implementieren Sie delegate / dataSource-Methoden (dh heightForRowAtgeben Sie einen Wert zurück UITableViewAutomaticDimension)

- -

Ziel c:

// in ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

  @property IBOutlet UITableView * table;

@end

// in ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    self.table.dataSource = self;
    self.table.delegate = self;

    self.table.rowHeight = UITableViewAutomaticDimension;
    self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return UITableViewAutomaticDimension;
}

Schnell:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

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

Für Label-Instanz in UITableviewCell

  • Stellen Sie die Anzahl der Zeilen auf 0 ein (& Zeilenumbruchmodus = Schwanz abschneiden)
  • Legen Sie alle Einschränkungen (oben, unten, rechts links) in Bezug auf die Übersicht / den Zellencontainer fest.
  • Optional : Legen Sie die Mindesthöhe für das Etikett fest, wenn der vertikale Mindestbereich durch das Etikett abgedeckt werden soll, auch wenn keine Daten vorhanden sind.

Geben Sie hier die Bildbeschreibung ein

Hinweis : Wenn Sie mehr als ein Etikett (UIElements) mit dynamischer Länge haben, das entsprechend seiner Inhaltsgröße angepasst werden sollte: Passen Sie die Priorität "Inhaltsumarmung und Kompressionswiderstand" für Etiketten an, die Sie mit höherer Priorität erweitern / komprimieren möchten.

Krunal
quelle
Implementierung von heightForRowAt mit Rückgabe der Arbeit
UITableView.automaticDimension
19

Stellen Sie außerdem sicher, dass die Linien für Ihr UILabel in der Zelle auf 0 gesetzt sind. Wenn sie auf 1 gesetzt sind, wächst sie nicht vertikal.

CamQuest
quelle
7

Ich habe einen bestimmten Fall und 99% der von mir gelesenen Lösungen haben nicht funktioniert. Ich dachte, ich würde meine Erfahrungen teilen. Ich hoffe, es kann helfen, da ich ein paar Stunden gekämpft hatte, bevor ich dieses Problem behoben hatte.

Mein Szenario :

  • Ich verwende zwei TableViews in einem ViewController
  • Ich lade benutzerdefinierte Zellen (xib) in diese Tabellenansichten
  • Dynamischer Inhalt in Zellen besteht aus zwei Beschriftungen
  • Seite verwendet eine ScrollView

Was ich erreichen musste :

  • Dynamische TableView-Höhe
  • Dynamische TableViewCells-Höhe

Was Sie überprüfen müssen, damit es reibungslos funktioniert :

  • Wie in jedem Tutorial und jeder Antwort angegeben, legen Sie alle Einschränkungen für Ihr Label / Ihren Inhalt (oben, unten, führend und nachfolgend) fest und setzen Sie sie auf ContentView (Superview). Dieses Video-Tutorial wird hilfreich sein .

  • In der viewWillAppearMethode meines ViewControllers gebe ich einer meiner tableViews ( tableView2) eine geschätzte Zeilenhöhe und verwende dann die UITableViewAutomaticDimensionals solche (und wie in allen Tutorials / Antworten zu sehen):

        override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        tableView2.estimatedRowHeight = 80
        tableView2.rowHeight = UITableViewAutomaticDimension
    
    }
    

Für mich waren diese vorherigen Schritte nicht genug. Meine TableView würde einfach die geschätzte Zeilenhöhe nehmen und sie mit der Anzahl der Zellen multiplizieren. Meeeh.

  • Als ich zwei verschiedene Tableviews verwendet werde, habe ich einen Ausgang für jeden von ihnen, tableView1und tableView2. Erlaubt mir, die Größe in der viewDidLayoutSubviewsMethode zu ändern . Fühlen Sie sich frei, im Kommentar zu fragen, wie ich das gemacht habe.

  • Ein zusätzlicher Schritt hat es für mich behoben, indem er dies zur viewDidAppearMethode hinzufügte :

    override func viewDidAppear(_ animated: Bool) {
    tableView1.reloadData() // reloading data for the first tableView serves another purpose, not exactly related to this question.
    tableView2.setNeedsLayout()
    tableView2.layoutIfNeeded()
    tableView2.reloadData()
    }
    

Hoffe das hilft jemandem!

Bptstmlgt
quelle
Der letzte Rat (aber ohne doppeltes IBOutlet) ist auch 2019 noch nützlich.
zhukov.ever
6

Ab iOS 11 und Xcode 9.3 sind die meisten der oben genannten Informationen falsch. Im Apple-Handbuch wird die Einstellung vorgeschlagen

    tableView.estimatedRowHeight = 85.0
    tableView.rowHeight = UITableViewAutomaticDimension

Die WWDC 2017-Sitzung 245 (Erstellen von Apps mit dynamischem Typ, ca. 16:33 im Video) schlägt etwas Ähnliches vor. Nichts davon machte einen Unterschied für mich.

Für eine Zelle im Untertitelstil müssen Sie lediglich die Anzahl der Zeilen (im Abschnitt Beschriftung des Attributinspektors) für Titel und Untertitel auf 0 setzen, um Zellen mit Tabellengröße in der Größe zu erhalten. Wenn eine dieser Beschriftungen zu lang ist und Sie die Anzahl der Zeilen nicht auf 0 setzen, passt die Größe der Tabellenansichtszelle nicht an.

Zampano
quelle
Einstellung numberOfLineszu 0für beide Etiketten können Sie selbst Sizing erhalten mit nicht angepassten UITableViewCells. Danke vielmals!
mxcl
5

Vergessen zu entfernen tableView(heightForRowAt:indexPath:)

Es kann sein, dass Sie wie ich versehentlich vergessen haben, den Boilerplate-Code für die heightForRowAtMethode zu entfernen .

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 60.0
}
Guy Daher
quelle
... und natürlich auch keine Höhenbeschränkung ;-)
Marcos
1
Sie können UITableViewAutomaticDimensionin dieser Methode zurückkehren. Für Unterklassen
Yanny
4

Für alle, die vielleicht das gleiche Problem mit mir hatten: Ich hatte eine Stunde lang Mühe, es zum Laufen zu bringen. Ein einfaches UIlabel mit Einschränkungen für oben, unten links und rechts. Ich habe die willDisplayCell verwendet, um die Daten an die Zelle zu übergeben, und dies verursachte Probleme bei der Zellenhöhe. Solange ich diesen Code in cellForRow eingefügt habe, hat alles einwandfrei funktioniert. Ich habe nicht verstanden, warum dies passiert ist. Vielleicht wurde die Zellenhöhe vor dem Aufruf von willDisplayCell berechnet, sodass kein Inhalt für die richtige Berechnung vorhanden war. Ich wollte nur erwähnen und wahrscheinlich jemandem mit dem gleichen Problem helfen.

Thomas
quelle
Vielen Dank! Auch ich habe mich um genau dieses Thema gekämpft. Scheint mir ein UIKit-Fehler zu sein, aber das hat es gelöst!
Gary Hooper
4

In iOS 11 und höher funktionierte es einwandfrei, während in iOS 10 die Lösung darin bestand, etwas hinzuzufügen

table.rowHeight = UITableView.automaticDimension
table.estimatedRowHeight = 200 // a number and not UITableView.automaticDimension

Stellen Sie außerdem sicher, dass Sie "heightForRowAt" hinzufügen, auch wenn es in iOS 11 und höher funktioniert. Dies ist erforderlich, wenn Sie iOS 10 unterstützen

   func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
Bassant Ashraf
quelle
3

In meinem Fall hatte ich zwei UITableViews, ich musste diese Methode als ändern

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    CGFloat height = 0.0;
    if (tableView == self.tableviewComments) {
        return UITableViewAutomaticDimension;
    }else if (tableView == self.tableViewFriends) {
        height = 44.0;
    }
    return height;
}
user1994956
quelle
3

Versuchen Sie dies, einfache Lösung, es funktioniert für mich,

In viewDidLoad schreiben Sie diesen Code,

-(void)viewDidLoad 
{
[super viewDidLoad];
 self.tableView.estimatedRowHeight = 100.0; // for example. Set your average height
 self.tableView.rowHeight = UITableViewAutomaticDimension;
}

Schreiben Sie in cellForRowAtIndexPath diesen Code:

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
  }
    cell.textLabel.numberOfLines = 0; // Set label number of line to 0
    cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"menu"];
    [cell.textLabel sizeToFit]; //set size to fit 
    return cell;
 }
Jaywant Khedkar
quelle
1

Für mein Setup habe ich zuerst die Einschränkungen im Storyboard überprüft, um festzustellen, UITableViewCellob sie von oben nach unten eindeutig sind, und musste dann den Code an zwei Stellen ändern.

  1. UITableViewDelegate's tableView(_:heightForRowAt:)

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
        // return UITableViewAutomaticDimension for older than Swift 4.2
    }
    
  2. UITableViewDelegate's tableView(_:estimatedHeightForRowAt:)

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
        // return UITableViewAutomaticDimension for older than Swift 4.2
    }
    

In Schritt 1 und 2 können Sie die automatische Größenanpassung nur für bestimmte Zeilen anwenden. UITableViewVerwenden Sie für die Bewerbung für das Ganze :

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
// return UITableViewAutomaticDimension for older than Swift 4.2
Pranav Kasetti
quelle
0

Damit UITableViewAutomaticDimension funktioniert, müssen Sie sicherstellen, dass alle Einschränkungen der 4 Ecken zur Übersicht hinzugefügt werden. In den meisten Fällen funktioniert es gut mit UILabel, aber manchmal finde ich, dass UITextView den Trick macht, wenn UILabel zu diesem Zeitpunkt nicht gut funktioniert. Versuchen Sie also, zu UITextView zu wechseln, und stellen Sie sicher, dass Scrolling Enableddas Kontrollkästchen im Storyboard deaktiviert ist. Sie können es auch programmgesteuert festlegen.

Terry Tan
quelle
0

Ich hatte drei horizontale Gegenstände und der am weitesten links liegende hatte eine Beschränkung auf den linken, der mittlere auf den oberen, unteren, linken und rechten Gegenstand. Der rechte hatte einen rechten und einen linken zum mittleren Gegenstand. Die Lösung bestand darin, dem mittleren Element (meinem Etikett) zusätzliche linke und rechte Einschränkungen hinzuzufügen, die> = eine Zahl in der Zelle waren.

Darko
quelle
0

Stellen Sie sicher, dass alle Ansichten in der Zelle auf die Inhaltsansicht und nicht auf die Zelle beschränkt sind.

Wie Apfel sagt:

Legen Sie den Inhalt der Zellen der Tabellenansicht in der Inhaltsansicht der Zelle an. Um die Höhe der Zelle zu definieren, benötigen Sie eine ununterbrochene Kette von Einschränkungen und Ansichten (mit definierten Höhen), um den Bereich zwischen der oberen und der unteren Kante der Inhaltsansicht auszufüllen.

Badr
quelle
0

Ich habe eine neue Lösung ... das hat bei mir funktioniert.

im Grunde UITableViewAutomaticDimensionumbenannt in UITableView.automaticDimension... Ich hoffe ... es ist wo

Yeasir Arafat Aronno
quelle