Ich habe eine gruppierte UITableview, die programmgesteuert erstellt wird. Außerdem habe ich eine Zelle mit einer XIB-Datei, die ebenfalls programmgesteuert in der Tabellenansicht ausgefüllt ist. So weit, ist es gut. Ich möchte aber nur die äußere Trennlinie entfernen. Ich habe den folgenden Code verwendet, aber diesmal alle Trennlinien entfernt.
self.tableView.separatorColor = [UIColor clearColor];
Dies ist keine gute Option für meine Situation. Hier ist der Screenshot, was ich tun möchte;
ios
objective-c
uitableview
cell
tableviewcell
Serhat Sezer
quelle
quelle
UIView
s als gefälschte Trennzeichen in die Zelle ein. Hoffentlich gibt es eine bessere Option.Plain tableview
nicht gruppiert zu verwenden. In Grouped werden in Kopf- und Fußzeilen Trennzeichen eingefügt.Antworten:
Ich habe gerade eine Lösung ausgearbeitet, da die Zelle eine
contentView
istUIView
, also denke ich, dass Sie sich nur auf das Endergebnis von konzentrieren könnencontentView
.Hier ist mein Code:
Zuerst müssen Sie das Trennzeichen löschen
tableView.separatorColor = UIColor.clear
Zweitens in der
cellForRowAt
Funktion:let bottomBorder = CALayer() bottomBorder.frame = CGRect(x: 0.0, y: 43.0, width: cell.contentView.frame.size.width, height: 1.0) bottomBorder.backgroundColor = UIColor(white: 0.8, alpha: 1.0).cgColor cell.contentView.layer.addSublayer(bottomBorder)
Hier sehen Sie die Benutzeroberfläche wie folgt:
quelle
Hier ist meine Lösung:
self.tableView.separatorColor = self.tableView.backgroundColor
quelle
Sie können Trennzeichen auch in gruppierten UITableView mit statischer Zelle entfernen:
class CustomCell: UITableViewCell { override func layoutSubviews() { super.layoutSubviews() for view in subviews where view != contentView { view.removeFromSuperview() } }
quelle
Google liefert diese Seite auch im Jahr 2018 als Top-Ergebnis für diese Frage. Ich hatte in iOS 11 kein Glück mit einer der bereitgestellten Antworten. Deshalb habe ich mir Folgendes ausgedacht:
extension UITableViewCell { func removeSectionSeparators() { for subview in subviews { if subview != contentView && subview.frame.width == frame.width { subview.removeFromSuperview() } } } }
Durch Aufrufen von .removeSectionSeparators () in einer beliebigen UITableViewCell-Instanz wird das Problem jetzt behoben. Zumindest in meinem Fall sind die Abschnitts-Trennzeichen die einzigen mit der gleichen Breite wie die Zelle selbst (da die anderen alle eingerückt sind).
Die einzige Frage ist, woher wir sie nennen sollen. Sie würden denken, dass willDisplayCell die beste Wahl wäre, aber ich habe festgestellt, dass der erste Aufruf erfolgt, bevor die Trennzeichenansichten selbst generiert werden, also keine Würfel.
Ich habe dies in meine cellForRowAtIndexPath-Methode eingefügt, kurz bevor ich eine neu geladene Zelle zurückgebe:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MyReusableIdentifier", for: indexPath) Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { (timer) in cell.removeSectionSeparators() } return cell }
Es fühlt sich nicht so elegant an, aber ich bin noch auf keine Probleme gestoßen.
EDIT: Sieht so aus, als ob wir das auch brauchen (für wiederverwendete Zellen):
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { cell.removeSectionSeparators() }
Hier ist ein Vorher / Nachher in Screenshots mit diesem Code:
Vor
Nach
quelle
Nach der Überprüfung der Ansichtshierarchie scheint jede UITableViewCell nur drei Unteransichten zu haben: die Inhaltsansicht (
UITableViewCellContentView
) und zwei Trennzeichenansichten (_UITableViewCellSeparatorView
). Ich bin kein Fan der dynamischen Klasseninstanziierung von NSStrings (und Apple auch nicht). Da auf dascontentView
of aUITableViewCell
jedoch ohne Verwendung privater APIs zugegriffen werden kann, ist die Lösung recht einfach.Die Idee ist nur, durch die Unteransichten von Ihnen zu iterieren
UITableViewCell
und alle Ansichten zu entfernen, die nicht die folgenden sindcontentView
:func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { let subviews = cell.subviews if subviews.count >= 3 { for subview in subviews { if subview != cell.contentView { subview.removeFromSuperview() break } } } }
tableView(:willDisplayCell:forRowAtIndexPath:)
wird beim Rendern von Tabellenansichten mehrmals aufgerufen, sodass der Status den Status verfolgt, indem überprüft wird, wie viele Unteransichten die Zelle hat. Wenn drei Unteransichten vorhanden sind, sind beide Trennzeichen noch intakt. Es wird auch nur eines der Trennzeichen entfernt, aber Sie können beide entfernen, indem Sie das entfernenbreak
. Sie können auch angeben, ob das obere oder das untere Trennzeichen entfernt werden soll, indem Sie den Rahmen der Unteransicht überprüfen. Wenn der Ursprung der y-Achse des Rahmens ist0
, ist dies das obere Trennzeichen. Wenn nicht0
, ist es der Boden.Hoffe das hilft!
Swift 4, Swift 4.2 Update:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { let subviews = cell.subviews guard subviews.count >= 3 else { return } for subview in subviews where NSStringFromClass(subview.classForCoder) == "_UITableViewCellSeparatorView" { subview.removeFromSuperview() } }
quelle
NSStringFromClass
diese Werte gegen und vergleichen"_UITableViewCellSeparatorView"
und"UITableViewCellContentView"
dann entfernen.#available
Attribut mit einem leeren Text für jede Version von iOS zu verwenden, die größer als die aktuelle Version ist.Zum Entfernen des oberen und unteren Teils der Trennlinie für jeden Abschnitt. Fügen Sie dies Ihrer statischen Zelle hinzu.
override func layoutSubviews() { super.layoutSubviews() //Get the width of tableview let width = subviews[0].frame.width for view in subviews where view != contentView { //for top and bottom separator will be same width with the tableview width //so we check at here and remove accordingly if view.frame.width == width { view.removeFromSuperview() } } }
Ergebnis wie unten abgebildet
quelle
Das ist eine wirklich alte Frage, dennoch ist es einer der ersten Einträge bei Google, wenn nach der Entfernung der oberen und unteren Trennzeichen für jeden Abschnitt gesucht wird.
Nach einigen Nachforschungen fand ich heraus, dass es keine Möglichkeit und keine Absicht von Apple gibt, dies irgendwie ohne dumm komplizierte Hacks der Ansichtshierarchie zu erreichen.
Glücklicherweise gibt es einen absolut einfachen und einfachen Weg, um einen solchen Look zu erzielen:
Ich sage einfach, aber für einen Anfänger kann dies schwierig sein, da er nicht versteht, wie es
UITableView
funktioniert und wie man eigene Zellen implementiert. Lassen Sie mich versuchen, es zu erklären:UITableViewCell
Unterklasse@IBOutlet weak var separatorView: UIView!
EigenschaftUITableView
sSeparator Style
auf einNone
, um das Standardtrennzeichen auszublendenUIView
auf Ihre Zelle und ändern Sie die Größe so, dass es sich unten (oder oben) in der Zelle befindet. Verwenden Sie dasSize Inspector
sAutoresizing
, um es an Start / Ende / unten zu stecken und ihm eine flexible Breite zu geben (oder Autolayout, aber das ist in diesem Fall etwas übertrieben).UITableViewDataSource
scellForRowAtIndexPath:
legen Sie dieisHidden
Eigenschaft Ihres benutzerdefinierten Trennzeichens fest, basierend darauf, ob dies dieindexPath.row
letzte Zeile (oder die erste, wenn sich Ihre Ansicht oben befindet) im Abschnitt istHier ist ein Beispielcode:
class MyCell: UITableViewCell { @IBOutlet weak var separatorView: UIView! } class ViewController: UITableViewController { override func numberOfSections(in tableView: UITableView) -> Int { return 3 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 3 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyCell cell.separatorView.isHidden = indexPath.row == 2 return cell } }
Und hier einige Screenshots:
Ja, es ist eine Arbeit, aber es gibt einfach keine Möglichkeit, beim Codieren etwas umsonst zu machen. Am Ende sind wir Programmierer und es liegt an uns, die Codierung durchzuführen. Es ist immer besser, die 5-10 Minuten damit zu verbringen, dies einzurichten, als nur das Einfügen von Hacky-Code zu kopieren, der möglicherweise in Zukunft nicht mehr funktioniert, wenn Apple beschließt, die Ansichtshierarchie zu ändern.
Es war tatsächlich mehr Arbeit, diese Antwort zu schreiben, als das Trennzeichen zu implementieren. Ich war auch auf der Suche nach einer einfachen und schnellen Lösung, aber am Ende gab es einfach keine, die meiner Meinung nach die Verwendung wert war.
Ich hoffe, Sie sind auch skeptisch, wenn Sie For-Loops sehen, die über Unteransichten von Zellen iterieren, um Ansichten zur Laufzeit aus der Ansichtshierarchie auszublenden oder sogar zu entfernen. Apple bietet Ihnen eine einfache, vielseitige, stabile und zukunftssichere Lösung gleich um die Ecke . 7 kleine Schritte sind wirklich alles was Sie brauchen und sie sind leicht zu verstehen.
quelle
Das habe ich mir endlich ausgedacht:
Ich konnte keinen besseren Weg finden. Aber es funktioniert sehr gut für mich. Zuletzt versucht mit Xcode Version 7.3.1 (7D1014). Dieser Vorgang wurde über das Storyboard durchgeführt.
Grundsätzlich füge ich der UITableViewCell eine UIView mit einer Höhe von 0,5 pt hinzu und lege dann eine Hintergrundfarbe für diese UIView fest. Setzen Sie das Trennzeichen des übergeordneten UITableView auf Keine.
Hier sind die Details:
Wenn Sie Ihre UITableViewCell bereits als benutzerdefiniert oder standardmäßig festgelegt haben. Setzen Sie in der ersten Phase das Trennzeichen von UITableView auf Keine.
Fügen Sie als Nächstes eine UIView mit einer Höhe von 1 Punkt hinzu und stellen Sie den Hintergrund nach Bedarf ein. In meinem Fall ist er Rot.
Beginnen Sie mit dem Festlegen der Einschränkungen. Das Problem besteht darin, die Höhe des UIView auf 0,5 pt einzustellen. Dies ist das einzige problematische Problem für diesen Workflow.
UIView mit 0,5 pt Höhe:
Teilen Sie den Weg, um die Höhe von 0,5 pt des UIView festzulegen.
Zuerst (1) die Ansicht fixieren und dann (2) die Höhe auf 0,5 einstellen. Drücken Sie Enter.
Schließlich sieht Ihr UIView wie folgt aus.
Ich konnte die Höhe nur auf diese Weise auf 0,5 einstellen.
quelle
Hier die Lösung. Dies gilt für statische Zellen. Wenn Sie dynamisch sein möchten, schreiben Sie einfach "count" neu. Ich hoffe es hilft.
extension NSObject { var theClassName: String { return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last! } } override func viewDidLoad() { super.viewDidLoad() tableView.separatorStyle = .None } override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { let count = tableView.numberOfRowsInSection(indexPath.section) if ( indexPath.row != count - 1 ) { for view in cell.subviews { if view.theClassName == "_UITableViewCellSeparatorView" { view.backgroundColor = UIColors.redColor() } } } }
quelle
Versuchte verschiedene Lösungen basierend auf der
cell.separatorInset = UIEdgeInsetsMake()
Problemumgehung, von denen keine richtig funktionierte.Für mein iOS11-
UITableViewStyleGrouped
basiertes Projekt hat dies Folgendes bewirkt :self.tableView.separatorColor = self.tableView.backgroundColor;
quelle
Basierend auf der Antwort des Kochs, aber ohne Timer:
override func didAddSubview(_ subview: UIView) { super.didAddSubview(subview) if NSStringFromClass(subview.classForCoder) != "UITableViewCellContentView" && subview.frame.width == frame.width { subview.removeFromSuperview() } }
Fügen Sie dies einfach in die Unterklasse einer Zelle ein und Sie brauchen nichts anderes. Funktioniert unter iOS 12.
quelle
iOS 13, Swift 5
In der benutzerdefinierten Zellenklasse:
override func layoutSubviews(){ super.layoutSubviews() for subview in subviews where (subview != contentView && abs(subview.frame.width - frame.width) <= 0.1 && subview.frame.height < 2) { subview.removeFromSuperview() //option #1 -- remove the line completely //subview.frame = subview.frame.insetBy(dx: 16, dy: 0) //option #2 -- modify the length } }
Ich möchte @cook für diese Lösung danken, die ich darauf aufgebaut habe. Ich hatte einige Probleme mit ihrer Lösung:
layoutSubviews()
und hatte kein einziges Problem.==
, was für mich fehleranfällig klingt.Ich habe die "Option 2" in den Code eingefügt, da dies die Lösung ist, nach der ich persönlich gesucht habe (ich wollte das Trennzeichen beibehalten, aber ich wollte, dass es auf der gleichen Einrückungsstufe wie die regulären Zellentrennzeichen ist, in meinem Fall a Wert von 16).
quelle
Ich hatte ein ähnliches Problem, bei dem ich eine gruppierte UITableView mit benutzerdefinierten Zellen hatte, die alle mit Interface Build als .xib-Dateien entworfen wurden. Die Zellen hatten einen weißen Hintergrund, entfernten die Standardtrennzeichen und fügten meine eigenen hinzu. Ich hatte auch benutzerdefinierte Header-Ansichten für jeden Abschnitt. Ich habe die Höhe dieser Header-Ansichten auf 44 festgelegt (kann alles sein ...). Zwischen meinen Abschnitten befand sich eine Ansicht mit einer Höhe von 1 Punkt, was seltsam schien. Anscheinend fügt das System zwischen den Abschnitten eine klare Hintergrundansicht hinzu, selbst wenn wir die benutzerdefinierte Höhe auf 44 festlegen und die von uns zurückgegebene benutzerdefinierte Kopfzeilenansicht ein Weiß (oder eine konkrete Hintergrundfarbe) aufweist. Die Farbe, die wir hinter dieser klaren Ansicht sehen, ist die Farbe des Hintergrunds der Tabellenansicht. In meinem Fall mussten sowohl die Tabellenansichten als auch die Zellen eine weiße Farbe haben. und das Setzen des Hintergrunds der Tabellenansicht auf Weiß löste das Problem (zumindest visuell, aber das wollte ich trotzdem). Die zweite Lösung wäre, den Stil der Tabellenansicht einfach zu halten, aber die UITableView-Delegatenmethode zu implementieren, um zwei oder mehr Abschnitte zurückzugeben, und bei Bedarf auch benutzerdefinierte Header zu erstellen. Dadurch bleiben die Header-Ansichten für eine Weile (während des Bildlaufs) oben, bis sich die Header-Ansicht des nächsten Abschnitts nähert, und dann steigt sie ebenfalls an (und das ist möglicherweise nicht das, was Sie wirklich wollen, aber dort kann ein einfacher Weg sein, dies zu beheben, aber nicht sicher).
quelle
Sie können mit auf die Ansicht zugreifen
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { let header = view as! UITableViewHeaderFooterView header.backgroundView . .....
quelle
Versuchen Sie dies, um die obere Trennlinie zu entfernen.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if(indexPath.row == 0 && indexPath.section == 0) { for (UIView *view in cell.subviews) { if ([NSStringFromClass([view class]) containsString:@"CellSeparator"]) { if (view.frame.origin.y == 0 && CGRectGetHeight(view.frame) < 1.01 ) { //Hide first UITableViewCellSeparatorView NSLog(@"%s Remove View From Cell[Section:0 Row:0] for top border [%@]:%@",__FUNCTION__,NSStringFromClass([view class]),view); view.hidden = YES; //Hide } } } } }
quelle
Bei einem Einzelzellenabschnitt reicht es aus, ihn einfach zu überschreiben
layoutSubviews
und leer zu lassen ! https://stackoverflow.com/a/59733571/4442627quelle
iOS 10 ~ 13 entfernt nur die Kopfzeile des Abschnitts.
-(void)layoutSubviews{ [super layoutSubviews]; //for iOS10~iOS13: only remove section head foot line for (UIView * v in self.subviews) { if ( v != self.contentView && (v.frame.size.width == self.frame.size.width)){ [v removeFromSuperview]; } } }
Wenn Sie alle Zeilen entfernen möchten:
for (UIView * v in self.subviews) { if (v != self.contentView){ [v removeFromSuperview]; } }
quelle
override func layoutSubviews() { super.layoutSubviews() subviews.filter { $0 != contentView && $0.frame.width == frame.width }.first?.removeFromSuperview() }
quelle
Hier ist eine Swift-Lösung, die unter iOS 8 und 9 funktioniert.
Definieren Sie ein Protokoll mit einer Standardimplementierung:
protocol CellSeparatorRemovable { } extension CellSeparatorRemovable { func removeSeparatorLinesFromCell(cell: UITableViewCell, section: Int, row: Int, indexPath: NSIndexPath) { guard (section, row) == (indexPath.section, indexPath.row) else { return } for view in cell.subviews where view != cell.contentView { view.removeFromSuperview() } } }
Passen Sie dann, wo immer Sie es verwenden möchten, das
CellSeparatorRemovable
Protokoll an und rufen Sie seine Methode auf von…willDisplayCell…
:class SomeVC: UITableViewController, CellSeparatorRemovable { override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { removeSeparatorLinesFromCell(cell, section: 1, row: 1, indexPath: indexPath) } }
Dies ist eine minimale Lösung; Möglicherweise müssen Sie es umgestalten, wenn Sie mit vielen Zellen arbeiten, um Probleme mit übermäßiger Rekursion und / oder Wiederverwendung von Zellen zu vermeiden.
quelle