iOS 8 UITableView Separator Inset 0 funktioniert nicht

662

Ich habe eine App, in der UITableViewder Trennzeicheneinsatz des Benutzers auf benutzerdefinierte Werte eingestellt ist - rechts 0, links 0. Dies funktioniert perfekt in iOS 7.x, aber iOS 8.0ich sehe, dass der Separator-Einschub auf den Standardwert von 15rechts gesetzt ist. Obwohl in den XIB-Dateien, auf die es eingestellt ist, 0wird es immer noch falsch angezeigt .

Wie entferne ich die UITableViewCellTrennränder?

user3570727
quelle
Haben Sie versucht, den Einschub auf 0,001 statt auf 0 zu setzen? Ich erinnere mich an ein ähnliches Problem, bei dem der Kanteneinsatz nicht auf 0, sondern auf 0,001 (oder etwas ähnlich Kleines) reagierte.
Freshking
Ich habe das versucht und es hat auch nicht funktioniert ..
user3570727
4
Dann würde ich vorschlagen, die Separatorfarbe auf einzustellen [UIColor clearColor]und eigene Separatoren zu zeichnen. Auf diese Weise sind Sie viel flexibler.
Freshking
1
Ich kann immer noch nicht glauben, dass dies immer noch nicht einer der UITableViewCellSeparatorStyleStandardeinstellungen ist. Sogar die akzeptierte Antwort ist meiner Meinung nach ein wirklich schmutziger Hack.
Enrico Susatyo

Antworten:

1071

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

Diese Eigenschaft ist unter iOS 7.0 nicht verfügbar. Sie müssen sie daher überprüfen, bevor Sie sie zuweisen.

Die einfache Lösung besteht darin, Ihre Zelle in Unterklassen zu unterteilen und die Layoutränder-Eigenschaft zu überschreiben, wie von @ user3570727 vorgeschlagen. Sie verlieren jedoch jegliches Systemverhalten wie das Erben von Rändern aus dem sicheren Bereich. Daher empfehle ich die folgende Lösung nicht:

(Ziel c)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // override any margins inc. safe area
}

(schnell 4.2):

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

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


Zusätzlich zu dieser layoutMarginsEigenschaft hat Apple Ihrer Zelle eine Eigenschaft hinzugefügt , die verhindert, dass die Randeinstellungen Ihrer Tabellenansicht übernommen werden. Wenn diese Eigenschaft festgelegt ist, können Ihre Zellen unabhängig von der Tabellenansicht ihre eigenen Ränder konfigurieren. Betrachten Sie es als Überschreibung.

Diese Eigenschaft wird aufgerufen preservesSuperviewLayoutMargins, und wenn Sie sie auf festlegen, NOkann die layoutMarginEinstellung der Zelle alle layoutMarginin Ihrer TableView festgelegten Einstellungen überschreiben . Beides spart Zeit ( Sie müssen die Einstellungen der Tabellenansicht nicht ändern ) und ist präziser. Eine ausführliche Erklärung finden Sie in der Antwort von Mike Abdullah.

HINWEIS: Was folgt, ist eine saubere Implementierung für eine Randeinstellung auf Zellebene , wie in der Antwort von Mike Abdullah ausgedrückt. Durch das Festlegen Ihrer Zellen preservesSuperviewLayoutMargins=NOwird sichergestellt, dass Ihre Tabellenansicht die Zelleneinstellungen nicht überschreibt. Wenn Sie tatsächlich möchten, dass Ihre gesamte Tabellenansicht konsistente Ränder aufweist, passen Sie Ihren Code entsprechend an.

Richten Sie Ihre Zellränder ein:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

Swift 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Remove seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Prevent the cell from inheriting the Table View's margin settings
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Explictly set your cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

Wenn Sie die preservesSuperviewLayoutMarginsEigenschaft für Ihre Zelle auf NEIN setzen, sollte verhindert werden, dass Ihre Tabellenansicht Ihre Zellenränder überschreibt. In einigen Fällen scheint es nicht richtig zu funktionieren.

Wenn alles fehlschlägt, können Sie Ihre Tabellenansichtsränder brutal erzwingen:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Force your tableview margins (this may be a bad idea)
    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()
    // Force your tableview margins (this may be a bad idea)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

... und los geht's! Dies sollte unter iOS 7 und 8 funktionieren.


BEARBEITEN: Mohamed Saleh machte mich auf eine mögliche Änderung in iOS 9 aufmerksam. Möglicherweise müssen Sie die Tabellenansichten auf einstellen cellLayoutMarginsFollowReadableWidth, NOwenn Sie Einfügungen oder Ränder anpassen möchten. Ihr Kilometerstand kann variieren, dies ist nicht sehr gut dokumentiert.

Diese Eigenschaft ist nur in iOS 9 vorhanden. Überprüfen Sie sie daher unbedingt, bevor Sie sie einstellen.

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

Swift 4:

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

(über Code von iOS 8 UITableView Separator Inset 0 funktioniert nicht )

EDIT: Hier ist ein reiner Interface Builder-Ansatz:

TableViewAttributesInspector TableViewCellSizeInspector

HINWEIS: iOS 11 ändert und vereinfacht einen Großteil dieses Verhaltens. Ein Update wird in Kürze veröffentlicht.

cdstamper
quelle
2
Für Tabellenansichten in einem UIPopoverController musste ich beide wie oben gezeigt ausführen, anstatt nur in der willDisplayCell.
Zhang
44
Ich fand auch heraus, dass ich trotz des obigen Codes immer noch cell.preservesSuperviewLayoutMargins = NOper @ bffmikes Vorschlag oder nach dem Scrollen eine Art und Weise hinzufügen musste, wie die Einfügungen erscheinen würden. (wtf ??)
anorganik
Was ist, wenn wir den Rand nur für einen Zelltyp in einer gruppierten Tabellenansicht festlegen möchten?
SAHM
Sie können versuchen, es in willDisplayCell festzulegen und zu prüfen, ob dies tatsächlich funktioniert (Sie haben ein Handle für die Zelle, daher sollte es trivial sein). Wenn dies nicht der Fall ist, müssen wir einen Fehler melden. Zellspezifische Layoutränder sollten möglich sein, IMO.
CD-Stamper
2
Dies funktionierte für mich mit der Hinzufügung von cell.preservesSuperviewLayoutMarginsin meiner Datenquellenmethode:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
mts
257

Arg !!! Nachdem Sie herumgespielt haben, tun Sie dies entweder in Ihrer CellUnterklasse:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

oder das cell.layoutMargins = UIEdgeInsetsZero;für mich fixiert einstellen .

user3570727
quelle
13
Die erste Lösung in dieser Antwort hat bei mir funktioniert, die zweite hat nicht funktioniert.
Spybart
5
Verwenden Sie nicht nur cell.layoutMargins = UIEdgeInsetsZero; wie es unter iOS 7.x abstürzen wird. Es ist besser zu überprüfen, ob der Selektor zuerst vorhanden ist, bevor Sie ihn verwenden. Siehe meine Lösung unten.
Ricky
3
Er setzt cell.layoutMargins nicht ... Diese Lösung funktioniert hervorragend, wenn Sie bereits benutzerdefinierte Zellen haben.
Sjoerd Perfors
11
Dies funktioniert gut in iOS 7, da die Methode nicht aufgerufen wird! Sie müssen jedoch auch die layoutMargins der Tabellenansicht festlegen, da dies sonst nicht funktioniert.
CD-Stamper
2
Das Überschreiben des Accessors hat für mich funktioniert. aber alle anderen Lösungen taten es nicht. Selbst die Konfiguration des separatorInsetin IB hat nicht funktioniert. Es gibt auch ein Problem mit den Hintergrundfarben der Tabellenansicht. Das ist wirklich krankes Zeug.
Glasz
178

Nehmen wir uns einen Moment Zeit, um das Problem zu verstehen, bevor wir blindlings aufladen, um zu versuchen, es zu beheben.

Ein kurzer Blick in den Debugger zeigt Ihnen, dass Trennlinien Unteransichten von sind UITableViewCell . Es scheint, dass die Zelle selbst eine angemessene Verantwortung für das Layout dieser Linien übernimmt.

iOS 8 führt das Konzept der Layoutränder ein . Standardmäßig befinden sich die Layoutränder einer Ansicht 8ptauf allen Seiten und werden von den Vorfahrenansichten geerbt .

Wie wir am besten erkennen können, wird beim Auslegen der Trennlinie UITableViewCellder linke Layoutrand berücksichtigt, um den linken Einschub einzuschränken.

Wenn wir all das zusammenfassen, um den gewünschten Einschub von wirklich Null zu erreichen, müssen wir:

  • Stellen Sie den linken Layoutrand auf ein 0
  • Stoppen Sie alle geerbten Ränder, die dies überschreiben

So ausgedrückt ist es eine ziemlich einfache Aufgabe:

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

Dinge zu beachten:

  • Dieser Code benötigt nur ausgeführt werden , einmal pro Zelle (Sie nur die Zelle der Eigenschaften schließlich Konfiguration), und es gibt nichts Besonderes , wenn Sie wählen , um es auszuführen. Tu, was dir am saubersten erscheint.
  • Leider ist keine der beiden Eigenschaften zum Konfigurieren in Interface Builder verfügbar, aber Sie können bei Bedarf ein benutzerdefiniertes Laufzeitattribut angeben preservesSuperviewLayoutMargins.
  • Wenn Ihre App auch auf frühere Betriebssystemversionen abzielt, müssen Sie die Ausführung des obigen Codes vermeiden, bis Sie unter iOS 8 und höher ausgeführt werden.
  • Anstatt Einstellungen vorzunehmen preservesSuperviewLayoutMargins, können Sie Vorfahrenansichten (z. B. die Tabelle) so konfigurieren, dass sie auch einen 0linken Rand haben. Dies scheint jedoch von Natur aus fehleranfälliger zu sein, da Sie nicht die gesamte Hierarchie steuern.
  • Es wäre wahrscheinlich etwas sauberer, nur den linken Rand zu setzen 0und die anderen zu lassen.
  • Wenn Sie eine 0-Einfügung in die "zusätzlichen" Trennzeichen wünschen, die UITableViewam unteren Rand von Tabellen im einfachen Stil gezeichnet werden, müssen Sie vermutlich auch auf Tabellenebene dieselben Einstellungen angeben (haben Sie diese nicht ausprobiert!).
Mike Abdullah
quelle
3
Vielen Dank! Dies ist wirklich die präzisere Antwort. Viel besser, als zwei Methoden zu überschreiben und sie brutal zu erzwingen.
LunaCodeGirl
16
In iOS 8 würde dies für mich nicht funktionieren[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12
1
Sie haben meine Stimme, danke für die klare Erklärung. Ich möchte nur erwähnen, dass die TableView selbst auch layoutMargins enthält, die in einigen Fällen zusätzlich zum separatorInset festgelegt werden müssen.
CD-Stamper
@ davetw12 und @cdstamper Können Sie dies nachweisen? Alle meine bisherigen Erkundungen besagen, dass das Einstellen von beiden layoutMarginsund preservesSuperviewLayoutMarginsder Zelle alles ist, was erforderlich ist. Alles andere fühlt sich an, als würde man auf Voodoo vertrauen.
Mike Abdullah
3
Nein, es ist keine Form von Voodoo @MikeAbdullah. Damit Sie den Standard vermeiden separatorInseteines UITableViewCellin iOS 8, müssen Sie den Satz setzen die UIEdgeInsetsNull auf beiden UITableViewund der UITableViewCell. Wenn Sie nicht beides tun, haben Sie immer noch einen linken Einschub, der größer als Null ist. Ich habe dies mehrfach bestätigt.
davetw12
58

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

In iOS 8 gibt es eine neue Eigenschaft für alle Objekte, von denen geerbt wird UIView. Also, die Lösung, um die einzustellenSeparatorInset Festlegen von in iOS 7.x in der UITableView in iOS 8 angezeigten Leerraum nicht entfernen.

Die neue Eigenschaft heißt " layoutMargins ".

@property(nonatomic) UIEdgeInsets layoutMargins
Description   The default spacing to use when laying out content in the view.
Availability  iOS (8.0 and later)
Declared In   UIView.h
Reference 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 festlegen, cell.layoutMargins = UIEdgeInsetsZero;ohne zu überprüfen, ob das layoutMarginsvorhanden ist, stürzt die App unter iOS 7.x ab. Der beste Weg wäre also zu überprüfen, ob das layoutMarginszuerst existiert setLayoutMargins:UIEdgeInsetsZero.

Ricky
quelle
Wie kann dieser Ansatz verwendet werden, wenn das Bereitstellungsziel auf iOS 7 festgelegt ist?
Petar
Ich habe den Code für tableView in viewDidLoad eingefügt und arbeite einwandfrei. Ich denke, es ist nicht notwendig, sie jedes Mal in willDisplayCell () aufzurufen.
Abdullah Umer
46

Sie können UIAppearance einmal beim Start Ihrer Anwendung (bevor die Benutzeroberfläche geladen wird) verwenden, um sie als globale Standardeinstellungen 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 den Code Ihres UIViewControllers sauber und können ihn jederzeit überschreiben, wenn Sie möchten.

Lukasz
quelle
41

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

Diese Eigenschaft ist in iOS 7.0 nicht verfügbar, daher müssen Sie sie überprüfen, bevor Sie sie zuweisen!

Allerdings hat Apple ein hinzugefügt Eigenschaft namens preservesSuperviewLayoutMargins für Ihr Handy , die es von vererben Ihrer Tabellenansicht der Randeinstellung zu verhindern. Auf diese Weise können Ihre Zellen unabhängig von der Tabellenansicht ihre eigenen Ränder konfigurieren. Betrachten Sie es als Überschreibung.

Diese Eigenschaft heißt preservesSuperviewLayoutMargins , und es NO Einstellung ermöglicht es Ihnen , Ihre Tabellenansicht der layoutMargin Einstellung mit Ihrer eigenen Zelle layoutMargin Einstellung außer Kraft zu setzen. Beides spart Zeit ( Sie müssen die Einstellungen der Tabellenansicht nicht ändern ) und ist präziser. Eine ausführliche Erklärung finden Sie in der Antwort von Mike Abdullah.

HINWEIS: Dies ist die richtige, weniger chaotische Implementierung, wie in der Antwort von Mike Abdullah ausgedrückt. Durch Festlegen der Vorbehalte Ihrer ZelleServerviewLayoutMargins = NO wird sichergestellt, dass Ihre Tabellenansicht die Zelleneinstellungen nicht überschreibt.

Erster Schritt - Richten Sie Ihre Zellränder ein:

/*
    Tells the delegate that the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath)
{
    // Remove separator inset
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

    // Explictly set your cell's layout margins
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }
}

Wenn Sie die EigenschafterveSuperviewLayoutMargins für Ihre Zelle auf NO setzen, sollte verhindert werden, dass Ihre Tabellenansicht Ihre Zellenränder überschreibt. In einigen Fällen scheint es nicht richtig zu funktionieren.

Zweiter Schritt - Nur wenn alles fehlschlägt, können Sie Ihre Tabellenansichtsränder brutal erzwingen:

/*
    Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Force your tableview margins (this may be a bad idea)
    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }

    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }
}

... und los geht's! Dies sollte sowohl unter iOS 8 als auch unter iOS 7 funktionieren.

Hinweis: Mit iOS 8.1 und 7.1 getestet. In meinem Fall musste ich nur den ersten Schritt dieser Erklärung verwenden.

Der zweite Schritt ist nur erforderlich, wenn Sie eine nicht ausgefüllte Zelle unter den gerenderten Zellen haben, d. H. Wenn die Tabelle größer als die Anzahl der Zeilen im Tabellenmodell ist. Wenn der zweite Schritt nicht ausgeführt wird, führt dies zu unterschiedlichen Trennzeichenversätzen.

König-Zauberer
quelle
1
Sie müssen in der willDisplayCellMethode nicht nach Selektoren suchen, da die Methode selbst bereits iOS 8+ ist und von älteren Versionen niemals aufgerufen wird.
Rivera
38

In Swift ist es etwas ärgerlicher, weil layoutMarginses eine Eigenschaft ist, also müssen Sie den Getter und den Setter überschreiben .

override var layoutMargins: UIEdgeInsets {
  get { return UIEdgeInsetsZero }
  set(newVal) {}
}

Dies wird effektiv layoutMarginsschreibgeschützt machen , was in meinem Fall in Ordnung ist.

Swilliams
quelle
Nur diese Lösung hat bei mir funktioniert. Und ich musste keinen zusätzlichen Zeilencode in die Methoden einfügen. Ich habe benutzerdefinierte Zellen verwendet.
Ramis
2
Für statische Zellen müssen Sie, abgesehen vom Überschreiben von layoutMargins, den Trennzeichenstil der Zelle weiterhin in "Benutzerdefinierte Einfügungen" ändern und den linken Wert im Storyboard auf "0" setzen.
Hufeng03
22

Für iOS 9 müssen Sie Folgendes hinzufügen:

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

Weitere Einzelheiten entnehmen Sie bitte der Frage .

Julian Król
quelle
12
Es ist lustig, Code für jede Version hinzuzufügen, damit das ursprüngliche Erscheinungsbild gleich bleibt ...
Christian
20

Swift 2.0-Erweiterung

Ich wollte nur eine Erweiterung freigeben, die ich gemacht habe, um die Ränder aus den Tabellenansicht-Zellentrennzeichen zu entfernen.

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector("setSeparatorInset:") {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
            self.preservesSuperviewLayoutMargins = false
        }

        if self.respondsToSelector("setLayoutMargins:") {
            self.layoutMargins = UIEdgeInsetsZero
        }
    }
}

Wird im Kontext verwendet:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    cell.removeMargins()
    return cell
Dan Beaulieu
quelle
15

Schnell:

override func viewDidLoad() {
    super.viewDidLoad()

    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }
    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }

    self.tableView.layoutIfNeeded()            // <--- this do the magic
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     ...

    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }

    return cell
}
Alexander Volkov
quelle
11

Ich habe es so gemacht:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
ideawu
quelle
9

In Bezug auf das, was cdstamper anstelle der Tabellenansicht vorgeschlagen hat, funktioniert das Hinzufügen der folgenden Zeilen in der layoutSubview-Methode der Zelle für mich.

- (void)layoutSubviews 
{
    [super layoutSubviews];

    if ([self respondsToSelector:@selector(setSeparatorInset:)])
                [self setSeparatorInset:UIEdgeInsetsZero];

        if ([self respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
        {
            [self setPreservesSuperviewLayoutMargins:NO];;
        }

        if ([self respondsToSelector:@selector(setLayoutMargins:)]) 
        {
            [self setLayoutMargins:UIEdgeInsetsZero];
        }
}
Vijay VS
quelle
9

Swift 3.0 Beispiel:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // removing seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // prevent the cell from inheriting the tableView's margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}
mkz
quelle
9

Nach langem Nachforschen ...

Hier ist die einzige Möglichkeit, dieses Zeug vollständig zu kontrollieren (das ich finden konnte)

Vollständige Steuerung der Trennzeicheneinfügungen und Layoutränder in jeder Zelle. Tun Sie dies in der willDisplayCellMethode auf Ihrem UITableviewDelegate.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.layoutMargins = UIEdgeInsetsZero
    cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

Das Zellenobjekt steuert das Trennzeichen und contentViewalles andere. Wenn die Leerzeichen Ihrer Trennzeichen in einer unerwarteten Farbe angezeigt werden, sollte dies folgende Probleme lösen:

cell.backgroundColor = cell.contentView.backgroundColor
Matjan
quelle
8

Einfache Lösung in Swift für iOS 8 mit einem benutzerdefiniertenUITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

Auf diese Weise setzen Sie layoutMarginund separatorInsetnur einmal, anstatt es für jedes zu tun, willDisplayCellwie die meisten der obigen Antworten vorschlagen.

Wenn Sie einen benutzerdefinierten Benutzer verwenden, ist UITableViewCelldies der richtige Ort, um dies zu tun. Ansonsten solltest du es in tun tableView:cellForRowAtIndexPath.

Nur ein weiterer Hinweis: Sie müssen nicht festlegen, preservesSuperviewLayoutMargins = falseda der Standardwert bereits ist NO!

Francesco Vadicamo
quelle
8

Für mich hat die einfache Linie den Job gemacht

cell.layoutMargins = UIEdgeInsetsZero
Apinho
quelle
wird in der Delegatenmethode cellForRowAtIndexPath aufgerufen. Gute Antwort :)
Saintjab
7

Fügen Sie einfach den folgenden Code hinzu, um dieses Programm zu lösen.

Viel Glück!

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

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

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

}
JimmyChang
quelle
5

Lukasz antwortet in Swift:

    // iOS 7:
    UITableView.appearance().separatorStyle = .SingleLine
    UITableView.appearance().separatorInset = UIEdgeInsetsZero
    UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

    // iOS 8:
    if UITableView.instancesRespondToSelector("setLayoutMargins:") {
        UITableView.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().preservesSuperviewLayoutMargins = false
    }
Naka
quelle
5

Dies ist der Code, der für mich in Swift funktioniert:

override func viewDidLoad() 
{
    super.viewDidLoad()
    ...
    if tableView.respondsToSelector("setSeparatorInset:") {
        tableView.separatorInset = UIEdgeInsetsZero
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset.left = CGFloat(0.0)
    }
    if tableView.respondsToSelector("setLayoutMargins:") {
        tableView.layoutMargins = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins.left = CGFloat(0.0)
    }
}

Dies scheint mir (vorerst) am saubersten zu sein, da alle Zellen- / Tabellenansicht-Kanten- / Randanpassungen in der tableView:willDisplayCell:forRowAtIndexPath:Methode vorgenommen werden, ohne unnötigen Code einzupferchen tableView:cellForRowAtIndexPath:.

Übrigens setze ich nur das linke SeparatorInset / layoutMargins der Zelle, weil ich in diesem Fall meine Einschränkungen, die ich in meiner Zelle eingerichtet habe, nicht vermasseln möchte.

Code aktualisiert auf Swift 2.2:

 override func viewDidLoad() {
   super.viewDidLoad()       

    if tableView.respondsToSelector(Selector("setSeparatorInset:")) {
      tableView.separatorInset = UIEdgeInsetsZero
        }
    }

 override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        if cell.respondsToSelector(Selector("setSeparatorInset:")) {
            cell.separatorInset.left = CGFloat(0.0)
        }
        if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
            tableView.layoutMargins = UIEdgeInsetsZero
        }
        if cell.respondsToSelector(Selector("setLayoutMargins:")) {
            cell.layoutMargins.left = CGFloat(0.0)
        }
    }
Ivan
quelle
Was genau funktioniert bei Ihnen nicht? Ich habe diesen Code gerade auf dem iPhone 5-Simulator getestet, auf dem das iOS 8.1 SDK installiert ist, und alles ist so, wie es war, als ich diese Antwort ursprünglich gepostet habe. Code wurde mit Xcode 6.1.1 kompiliert und ausgeführt.
Ivan
4

Die meisten Antworten zeigen Separator Einfügungen und Layout - Ränder über eine Vielzahl von Verfahren eingestellt werden (dh viewDidLayoutSubviews, willDisplayCellusw.) für Zellen und Tableviews, aber ich habe festgestellt , dass diese in nur darum , cellForRowAtIndexPathgroßen Werken. Scheint der sauberste Weg zu sein.

// kill insets for iOS 8
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
    cell.preservesSuperviewLayoutMargins = NO;
    [cell setLayoutMargins:UIEdgeInsetsZero];
}
// iOS 7 and later
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
    [cell setSeparatorInset:UIEdgeInsetsZero];
anorganik
quelle
4

Verwenden Sie das folgende Code-Snippet, um unerwünschte Auffüllprobleme für UITableView in IOS 8 und 7 zu vermeiden.

-(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];
    }
}
Anooj VM
quelle
4

Anstatt zu aktualisieren preservesSuperviewLayoutMarginsund layoutMarginsjedes Mal, wenn die Zelle einen Bildlauf durchführt (mit willDisplayCell), würde ich vorschlagen, dies einmal zu tun cellForRowAtIndexPath::

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)

    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero

    return cell

}
Rudolf Adamkovič
quelle
4

Hier ist eine einfache Möglichkeit, den Einschub global zu entfernen.

In UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

  override public var layoutMargins: UIEdgeInsets {
    get { return UIEdgeInsetsZero }
    set { }
  }

}

In AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Sie könnten denken, a) auch nur separatorInsetin der Erweiterung überschreiben oder b) layoutMarginsstattdessen den Erscheinungs-Proxy für festlegen . Beides wird nicht funktionieren. Obwohl separatorInsetangegeben wird, dass es sich um eine Eigenschaft handelt, führt der Versuch, sie als Eigenschaft (oder Methode) zu überschreiben, zu Compilerfehlern. Das Festlegen des Erscheinungs-Proxys für UITableViewCell's layoutMargins(oder auch das Festlegen der Erscheinungs-Proxys für UITableView' s layoutMarginsund separatorInset) hat keine Auswirkung.

Scott Gardner
quelle
3

In iOS8:

Hinzufügen zu meiner UITableViewCell-Unterklasse:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

und dies zu "tableView: cellForRowAtIndexPath" oder "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

Für mich gearbeitet.

Saru
quelle
2
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        // ... Get the cell
        cell.separatorInset = UIEdgeInsetsMake(0.f, 20.f, 0.f, [UIScreen mainScreen].bounds.size.width - 20);
        // others
        return cell;
}

Für eine bestimmte Zelle möchten Sie das Trennzeichen ausblenden.

xmurobi
quelle
2

Nachdem ich die Antworten in Etage 3 gesehen hatte, versuchte ich herauszufinden, in welcher Beziehung das Einrichten des Trennzeichens zwischen TableView und TableViewCell steht, und führte einige Tests durch. Hier sind meine Schlussfolgerungen:

  1. Wir können davon ausgehen, dass das Setzen des Trennzeichens der Zelle auf Null das Trennzeichen in zwei Schritten verschieben muss: Der erste Schritt besteht darin, das Trennzeichen der Zelle auf Null zu setzen. Der zweite Schritt besteht darin, das Randlayout der Zelle auf Null zu setzen.

  2. stellen Sie die die Tableview separatorinset und marginlayout kann der Zelle beeinflussen separatorinset . Aus dem Test geht jedoch hervor, dass das Separator- Set von TableView nutzlos zu sein scheint. Das Marginlayout von TableView kann sich tatsächlich auf das Marginlayout der Zelle auswirken .

  3. Wenn Sie PreservesSuperviewLayoutMargins = false von Cell festlegen , kann der Marginlayout- Effekt von TableView für Zellen abgeschnitten werden .

  4. eine der Lösungen:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }
Xin Chen
quelle
2

Das ist meine Lösung. Dies gilt für die benutzerdefinierte Zellenunterklasse. Fügen Sie beide einfach zur Unterklasse hinzu.

  1. - (UIEdgeInsets)layoutMargins {    
        return UIEdgeInsetsMake(0, 10, 0, 10);
    }

2.

self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);

Und es ist praktisch, dass Sie die Position des Trennzeichens anpassen können, ohne Ihren Designer zu bitten, eines für Sie zu zeichnen ..........

Guoyu
quelle
1

Kompakter als die am meisten gewählte Antwort ...

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

    if ([cell respondsToSelector:@selector(setSeparatorInset:)] && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)] && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
         [cell setSeparatorInset:UIEdgeInsetsZero];
         [cell setPreservesSuperviewLayoutMargins:NO];
         [cell setLayoutMargins:UIEdgeInsetsZero];
    }

}}

Subharb
quelle
1

Das Hinzufügen dieses Snippets, einfach elegant in Swift, funktioniert für mich in iOS8 :)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}
ddnl
quelle
1

Dies funktionierte perfekt für mich in iOS 8 und iOS 9.

Für OBJ-C

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(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];
        }
         return cell;
    }
Jithin
quelle