686 Stimmen

IOS 8 UITableView Separator Einfügung 0 funktioniert nicht.

Ich habe eine App, in der der UITableView Separator-Einsatz auf benutzerdefinierte Werte - Rechts 0, Links 0 - festgelegt ist. Dies funktioniert perfekt in iOS 7.x, jedoch in iOS 8.0 sehe ich, dass der Separator-Einsatz standardmäßig auf 15 rechts gesetzt ist. Obwohl es in den xib-Dateien auf 0 eingestellt ist, wird es trotzdem falsch angezeigt.

Wie entferne ich die Ränder des UITableViewCell Separators?

1077voto

chris stamper Punkte 12923

iOS 8.0 führt die layoutMargins-Eigenschaft für Zellen UND Tabellenansichten ein.

Diese Eigenschaft ist auf iOS 7.0 nicht verfügbar, also müssen Sie sicherstellen, dass Sie überprüfen, bevor Sie sie zuweisen!

Die einfache Lösung besteht darin, Ihre Zelle zu unterklassifizieren und die layoutMargins-Eigenschaft gemäß der Empfehlung von @user3570727 zu überschreiben. Sie verlieren jedoch jedes Systemverhalten wie das Erben von Rändern vom sicheren Bereich, also empfehle ich nicht die folgende Lösung:

(ObjectiveC)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // überschreibt alle Ränder inkl. sicherem Bereich
}

(swift 4.2):

override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }

Wenn Sie die Eigenschaft nicht überschreiben möchten oder sie bedingt setzen müssen, lesen Sie weiter.


Zusätzlich zur layoutMargins-Eigenschaft hat Apple Ihrem Zelle eine Eigenschaft hinzugefügt, die verhindert, dass sie die Rand-Einstellungen Ihrer Tabellenansicht erbt. Wenn diese Eigenschaft gesetzt ist, können Ihre Zellen ihre eigenen Ränder unabhängig von der Tabellenansicht konfigurieren. Denken Sie daran wie eine Überschreibung.

Diese Eigenschaft nennt sich preservesSuperviewLayoutMargins und das Setzen auf NO ermöglicht es der Zelle, die layoutMargin-Einstellung der Tabellenansicht zu überschreiben. Das spart Zeit (Sie müssen nicht die Einstellungen der Tabellenansicht ändern) und ist prägnanter. Bitte beachten Sie die Antwort von Mike Abdullah für eine detaillierte Erklärung.

HINWEIS: Im Folgenden finden Sie eine saubere Implementierung für eine Randen-Einstellung auf Zellebene, wie sie in der Antwort von Mike Abdullah beschrieben ist. Wenn Sie möchten, dass Ihre gesamte Tabellenansicht konsistente Ränder hat, passen Sie Ihren Code entsprechend an.

Richten Sie Ihre Zellenränder ein:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Trennlinieneinrückung entfernen
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Verhindern, dass die Zelle die Rand-Einstellungen der Tabellenansicht erbt
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Legen Sie explizit die Randmargen Ihrer Zelle fest
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

Swift 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Trennlinieneinrückung entfernen
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Verhindern, dass die Zelle die Rand-Einstellungen der Tabellenansicht erbt
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Legen Sie explizit die Randmargen Ihrer Zelle fest
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

Das Setzen der preservesSuperviewLayoutMargins-Eigenschaft auf Ihrer Zelle auf NEIN sollte verhindern, dass Ihre Tabellenansicht Ihre Zellenränder überschreibt. In einigen Fällen scheint es jedoch nicht ordnungsgemäß zu funktionieren.

Wenn alles fehlschlägt, können Sie Ihre Tabellenansichtsränder gewaltsam ändern:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Erzwingen der Tabellenansichtsränder (könnte eine schlechte Idee sein)
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
} 

Swift 4:

func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Erzwingen der Tabellenansichtsränder (könnte eine schlechte Idee sein)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

...und da haben Sie es! Dies sollte auf iOS 7 und 8 funktionieren.


ÄNDERUNG: Mohamed Saleh hat mich auf eine mögliche Änderung in iOS 9 aufmerksam gemacht. Sie müssen möglicherweise die Eigenschaft der Tabellenansicht cellLayoutMarginsFollowReadableWidth auf NO setzen, wenn Sie Abstände oder Ränder anpassen möchten. Ihre Erfahrung kann variieren, da dies nicht sehr gut dokumentiert ist.

Diese Eigenschaft existiert nur in iOS 9, also stellen Sie sicher, dass Sie vor dem Setzen überprüfen.

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

Swift 4:

if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
    myTableView.cellLayoutMarginsFollowReadableWidth = false
}

(obiger Code von iOS 8 UITableView separator inset 0 not working)

ÄNDERUNG: Hier ist ein reiner Interface Builder-Ansatz:

TableViewAttributesInspector TableViewCellSizeInspector

HINWEIS: iOS 11 ändert und vereinfacht einen Großteil dieses Verhaltens, ein Update wird folgen...

260voto

user3570727 Punkte 10193

Arg!!! Nachdem ich ein bisschen herumgespielt habe, habe ich entweder dies in Ihrer Cell-Unterklasse gemacht:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

oder indem ich cell.layoutMargins = UIEdgeInsetsZero; gesetzt habe, hat es für mich funktioniert.

179voto

Mike Abdullah Punkte 14832

Lassen Sie uns einen Moment Zeit, um das Problem zu verstehen, bevor wir blind versuchen, es zu beheben.

Ein schneller Blick in den Debugger zeigt, dass Trennlinien Untersichten von UITableViewCell sind. Es scheint, dass die Zelle selbst eine beträchtliche Verantwortung für das Layout dieser Linien übernimmt.

iOS 8 führt das Konzept der Layoutränder ein. Standardmäßig beträgt der Layoutrand einer Ansicht auf allen Seiten 8pt und er wird von Vorgängeransichten vererbt.

Soweit wir sehen können, wählt UITableViewCell beim Layouten seiner Trennlinie aus, den linken Layoutrand zu respektieren, und verwendet ihn, um den linken Einzug einzuschränken.

Um den gewünschten Einzug tatsächlich auf null zu erreichen, müssen wir folgendes tun:

  • Setzen Sie den linken Layoutrand auf 0
  • Verhindern Sie, dass vererbte Ränder dies überschreiben

So ausgedrückt ist es eine ziemlich einfache Aufgabe zu erledigen:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

Zu beachten:

  • Dieser Code muss nur einmal pro Zelle ausgeführt werden (Sie konfigurieren schließlich nur die Eigenschaften der Zelle), und es ist nichts Besonderes, wann Sie ihn ausführen. Tun Sie, was Ihnen am saubersten erscheint.
  • Leider sind beide Eigenschaften nicht in Interface Builder konfigurierbar, aber Sie können ein benutzerdefiniertes Laufzeitattribut für preservesSuperviewLayoutMargins angeben, wenn gewünscht.
  • Offensichtlich müssen Sie, wenn Ihre App auch auf frühere Betriebssystemversionen abzielt, den obigen Code erst ausführen, wenn iOS 8 und höher ausgeführt wird.
  • Statt preservesSuperviewLayoutMargins zu setzen, können Sie Vorgängeransichten (wie die Tabelle) konfigurieren, um ebenfalls einen linken Rand von 0 zu haben, aber dies scheint inhärent fehleranfälliger zu sein, da Sie nicht die gesamte Hierarchie kontrollieren.
  • Es wäre wahrscheinlich etwas sauberer, nur den linken Rand auf 0 zu setzen und die anderen beizubehalten.
  • Wenn Sie einen Einzug von 0 auf den "zusätzlichen" Trennlinien haben möchten, die UITableView am unteren Rand von Tabellen im schlichten Stil zeichnet, vermute ich, dass dies auch eine spezifische Einstellung auf Tabellenebene erfordern wird (habe dies nicht ausprobiert!)

60voto

Ricky Punkte 10485

Ich glaube, dies ist dieselbe Frage, die ich hier gestellt habe: Entfernen Sie SeparatorInset auf iOS 8 UITableView für XCode 6 iPhone Simulator

In iOS 8 gibt es eine neue Eigenschaft für alle Objekte, die von UIView erben. Die Lösung, um den SeparatorInset in iOS 7.x festzulegen, wird daher diesen Weißraum nicht entfernen, den Sie auf der UITableView in iOS 8 sehen.

Die neue Eigenschaft heißt "layoutMargins".

@property(nonatomic) UIEdgeInsets layoutMargins
Beschreibung   Der Standardabstand, der beim Layouten des Inhalts im View verwendet wird.
Verfügbarkeit  iOS (8.0 und höher)
Deklariert In   UIView.h
Referenz UIView Class Reference

iOS 8 UITableView setSeparatorInset:UIEdgeInsetsZero setLayoutMargins:UIEdgeInsetsZero

Die Lösung:-

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [tableView setLayoutMargins:UIEdgeInsetsZero];
    }

   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}

Wenn Sie cell.layoutMargins = UIEdgeInsetsZero; setzen, ohne zu überprüfen, ob layoutMargins existiert, wird die App auf iOS 7.x abstürzen. Daher wäre es am besten, zuerst zu überprüfen, ob layoutMargins existiert, bevor Sie setLayoutMargins:UIEdgeInsetsZero setzen.

47voto

Lukasz Punkte 19384

Sie können UIAppearance einmal verwenden, beim Start Ihrer Anwendung (bevor die Benutzeroberfläche geladen wird), um es als Standardglobale Einstellungen festzulegen:

// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];

[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {

    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];

}

Auf diese Weise halten Sie Ihren UIViewController-Code sauber und können ihn jederzeit überschreiben, wenn Sie möchten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X