So legen Sie die Breite einer Zelle in einer UITableView in gruppiertem Stil fest

107

Ich arbeite seit ungefähr 2 Tagen daran und dachte, ich teile meine Erkenntnisse mit Ihnen.

Die Frage ist: Ist es möglich, die Breite einer Zelle in einer gruppierten UITableView zu verkleinern?

Die Antwort ist nein.

Es gibt jedoch zwei Möglichkeiten, um dieses Problem zu umgehen.

Lösung 1: Eine dünnere Tabelle Es ist möglich, den Rahmen der tableView so zu ändern, dass die Tabelle kleiner wird. Dies führt dazu, dass UITableView die Zelle im Inneren mit der reduzierten Breite rendert.

Eine Lösung hierfür kann folgendermaßen aussehen:

-(void)viewWillAppear:(BOOL)animated
{
    CGFloat tableBorderLeft = 20;
    CGFloat tableBorderRight = 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
    tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
    tableView.frame = tableRect;
}

Lösung 2: Zellen durch Bilder rendern lassen

Diese Lösung wird hier beschrieben: http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html

Ich hoffe, diese Informationen sind hilfreich für Sie. Ich habe ungefähr 2 Tage gebraucht, um viele Möglichkeiten auszuprobieren. Dies ist, was übrig blieb.

Tomen
quelle
3
Ich denke, dies hätte als Frage mit nur der zweiten Zeile ("Die Frage ist: ...") eingerichtet werden sollen, dann wurden Lösung 1 und Lösung 2 als zwei separate Antworten veröffentlicht, von denen eine akzeptiert wurde. Wenn dann andere Benutzer ihre eigenen Antworten hinzufügen und einer von ihnen besser wird, kann die akzeptierte Antwort später geändert werden.
GeneralMike

Antworten:

226

Ein besserer und sauberer Weg, dies zu erreichen, besteht darin, UITableViewCell zu unterordnen und seine -setFrame:Methode wie folgt zu überschreiben :

- (void)setFrame:(CGRect)frame {
    frame.origin.x += inset;
    frame.size.width -= 2 * inset;
    [super setFrame:frame];
}

Warum ist es besser? Weil die anderen beiden schlimmer sind.

  1. Passen Sie die Breite der Tabellenansicht in an -viewWillAppear:

    Erstens ist dies unzuverlässig. Die Übersicht oder der übergeordnete Ansichtscontroller können den Tabellenansichtsrahmen nach dem -viewWillAppear:Aufruf weiter anpassen . Natürlich können Sie -setFrame:für Ihre UITableView genau wie das, was ich hier für UITableViewCells mache , Unterklassen erstellen und überschreiben . Die Unterklasse von UITableViewCells ist jedoch eine weit verbreitete, leichte und Apple-Methode.

    Zweitens, wenn Ihre UITableView über backgroundView verfügt, möchten Sie nicht, dass die backgroundView zusammen eingegrenzt wird. Die Breite von backgroundView beizubehalten, während die Breite von UITableView eingegrenzt wird, ist keine triviale Arbeit, ganz zu schweigen davon, dass das Erweitern von Unteransichten über die Übersicht hinaus überhaupt nicht sehr elegant ist.

  2. Benutzerdefiniertes Zellen-Rendering zum Fälschen einer schmaleren Breite

    Dazu müssen Sie spezielle Hintergrundbilder mit horizontalen Rändern vorbereiten und Unteransichten von Zellen selbst anordnen, um die Ränder aufzunehmen. Im Vergleich dazu erledigt die automatische Größenänderung alle Arbeiten für Sie, wenn Sie einfach die Breite der gesamten Zelle anpassen.

an0
quelle
2
Dies ist eine schöne und elegante Lösung, ich habe es in einer Kategorie gemacht :) Ich würde auch bemerken, dass je transparenter Objekte, desto mehr CPU-Belastung :)
Mister Koz
11
@misterkoz - ein Wort der Vorsicht: Einige iOS-Steuerelemente (UIDatePicker für bestimmte) verwenden intern UITableViewCells und brechen, wenn Sie dies in einer Kategorie implementieren.
Clafou
7
Diese Methode scheint in iOS8 nicht zu funktionieren, wenn versucht wird, eine Zelle im Bearbeitungsmodus zu entfernen. Der setFrame wird aufgerufen, wenn Sie den Bearbeitungsmodus aktivieren / beenden, damit die Zelle immer kleiner wird. Irgendeine Lösung dafür?
John Baum
3
@ JohnBaum dies könnte helfen (zumindest in meinem Fall funktioniert es): stackoverflow.com/questions/25911484/ios-8-cell-resizing/…
HashtagMarkus
2
Diese Lösung ist wirklich ein Glücksfall. Für den Fall, dass sich jemand fragt, wie man das gleiche schnell macht - reddit.com/r/swift/comments/2fr849/…
sysuser
16

Um dies in Swift zu tun, das keine Methoden zum Festlegen von Variablen bereitstellt, müssen Sie den Setter für überschreiben frame. Ursprünglich (zumindest , wo ich es gefunden) geschrieben hier

override var frame: CGRect {
    get {
        return super.frame
    }
    set (newFrame) {
        let inset: CGFloat = 15
        var frame = newFrame
        frame.origin.x += inset
        frame.size.width -= 2 * inset
        super.frame = frame
    }
}
JuJoDi
quelle
Funktioniert für Swift
Simon McNeil
9

Wenn nichts funktioniert, können Sie dies versuchen

Stellen Sie die Hintergrundfarbe der Zelle als klare Farbe ein und fügen Sie dann ein Bild der Zelle mit der erforderlichen Größe ein. Wenn Sie Text in dieser Zelle anzeigen möchten, platzieren Sie eine Beschriftung über dem Bild. Vergessen Sie nicht, die Hintergrundfarbe des Etiketts auch auf klare Farbe einzustellen.

includeMe
quelle
8

Ich fand, dass die akzeptierte Lösung bei Rotation nicht funktionierte. Um UITableViewCells mit festen Breiten und flexiblen Rändern zu erzielen, habe ich die obige Lösung wie folgt angepasst:

- (void)setFrame:(CGRect)frame {

    if (self.superview) {
        float cellWidth = 500.0;
        frame.origin.x = (self.superview.frame.size.width - cellWidth) / 2;
        frame.size.width = cellWidth;
    }

    [super setFrame:frame];
}

Die Methode wird immer dann aufgerufen, wenn sich das Gerät dreht, sodass die Zellen immer zentriert sind.

Graham
quelle
0

Es gibt eine Methode, die aufgerufen wird, wenn der Bildschirm gedreht wird: viewWillTransitionToSize

Hier sollten Sie die Größe des Rahmens ändern. Siehe Beispiel. Ändern Sie die Rahmenkoordinaten nach Bedarf.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        int x = 0;
        int y = 0;
        self.tableView.frame = CGRectMake(x, y, 320, self.tableView.frame.size.height);
    }];
}
Kerl
quelle
-2

Ich mache es in

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    CGFloat tableBorderLeft = self.view.frame.origin.x + 10;
    CGFloat tableBorderRight = self.view.frame.size.width - 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x = tableBorderLeft; 
    tableRect.size.width = tableBorderRight; 
    tableView.frame = tableRect;
}

Und das hat bei mir funktioniert

Lều Đức Quý
quelle
-6

Fügen Sie in der .h-Datei den Delegaten 'UITableViewDataSource' hinzu.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    return size;
}
Bharath Gangupalli
quelle
4
Er will die Breite einstellen, nicht die Höhe
Christopher Pickslay
oh hoo. sry für Unannehmlichkeiten.
Bharath Gangupalli
Du verstehst die Frage falsch und antwortest auf Höhe und du weißt, was es für mich funktioniert, weil ich nach Höhe suche, nicht nach Breite. Danke für die Antwort
Pooja