Seit ich herausgefunden habe, dass AutoLayout
ich es überall benutze, versuche ich es jetzt mit einem zu benutzen tableHeaderView
.
Ich habe eine subclass
von UIView
hinzugefügt alles (Etiketten etc ...) ich mit ihren Zwängen wollte, dann habe ich diese CustomView
mit dem UITableView
' tableHeaderView
.
Alles funktioniert gut , außer den UITableView
immer Displays über die CustomView
, von oben Ich meine das CustomView
ist unter dem UITableView
so ist es nicht zu sehen!
Es scheint , dass egal , was ich tue, die height
von den UITableView
' tableHeaderView
ist immer 0 (so ist die Breite x und y).
Meine Frage: Ist das überhaupt möglich, ohne den Rahmen manuell einzustellen ?
EDIT:
Das CustomView
' subview
, das ich benutze, hat diese Einschränkungen:
_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];
Ich verwende eine praktische Bibliothek 'KeepLayout', da das manuelle Schreiben von Einschränkungen ewig dauert und viel zu viele Zeilen für eine einzelne Einschränkung enthält, die Methoden jedoch selbsterklärend sind.
Und das UITableView
hat diese Einschränkungen:
_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];
_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;
Ich weiß nicht, ob ich einige Einschränkungen direkt CustomView
für das festlegen muss. Ich denke, die Höhe der benutzerdefinierten Ansicht wird durch die Einschränkungen für den darin enthaltenen UILabel
"Titel" bestimmt.
BEARBEITEN 2: Nach einer weiteren Untersuchung scheinen Höhe und Breite der benutzerdefinierten Ansicht korrekt berechnet zu sein, aber die Oberseite der benutzerdefinierten Ansicht befindet sich immer noch auf der gleichen Ebene wie die Oberseite der UITableView und sie bewegen sich beim Scrollen zusammen.
quelle
Antworten:
Ich habe hier eine ähnliche Frage gestellt und beantwortet . Zusammenfassend füge ich den Header einmal hinzu und benutze ihn, um die erforderliche Höhe zu finden. Diese Höhe kann dann auf den Header angewendet werden, und der Header wird ein zweites Mal festgelegt, um die Änderung widerzuspiegeln.
Wenn Sie mehrzeilige Beschriftungen haben, hängt dies auch von der benutzerdefinierten Ansicht ab, in der die bevorzugte maximale Layoutbreite für jede Beschriftung festgelegt ist:
oder vielleicht allgemeiner:
Update Januar 2015
Leider scheint dies immer noch notwendig. Hier ist eine schnelle Version des Layoutprozesses:
Ich fand es nützlich, dies in eine Erweiterung von UITableView zu verschieben:
Verwendung:
quelle
preferredMaxLayoutWidth
besteht darin, der Kopfzeile vor der Verwendung eine Breitenbeschränkung (die der Breite der Tabellenansicht entspricht) hinzuzufügensystemLayoutSizeFittingSize:
.self.tableView.tableHeaderView
let height = header.systemLayoutSizeFittingSize(CGSizeMake(CGRectGetWidth(self.bounds), 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
header.setNeedsLayout() header.layoutIfNeeded() header.frame.size = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) self.tableHeaderView = header
würde unter iOS 10.2Ich konnte keine Header-Ansicht mithilfe von Einschränkungen (im Code) hinzufügen. Wenn ich meiner Ansicht eine Breiten- und / oder Höhenbeschränkung gebe, wird ein Absturz mit der Meldung angezeigt:
Wenn ich meiner Tabellenansicht eine Ansicht im Storyboard hinzufüge, werden keine Einschränkungen angezeigt, und sie funktioniert gut als Kopfzeilenansicht. Daher denke ich, dass die Platzierung der Kopfzeilenansicht nicht mithilfe von Einschränkungen erfolgt. Es scheint sich in dieser Hinsicht nicht wie eine normale Sichtweise zu verhalten.
Die Breite ist automatisch die Breite der Tabellenansicht. Sie müssen lediglich die Höhe festlegen. Die Ursprungswerte werden ignoriert, sodass es keine Rolle spielt, was Sie für diese eingeben. Zum Beispiel hat dies gut funktioniert (wie auch 0,0,0,80 für das Rect):
quelle
translatesAutoresizingMaskIntoConstraints = NO
. Das Aktivieren der Übersetzung verhindert den Fehler. Ich vermute, dassUITableView
ab 7.1 nicht versucht wird, die Header-Ansicht automatisch auszurichten, und dass etwas mit dem voreingestellten Frame gewünscht wird.Ich habe hier viele Methoden gesehen, die so viel unnötiges getan haben, aber Sie brauchen nicht so viel, um das automatische Layout in der Kopfzeile zu verwenden. Sie müssen nur Ihre xib-Datei erstellen, Ihre Einschränkungen festlegen und sie wie folgt instanziieren:
quelle
Eine andere Lösung besteht darin, die Erstellung der Header-Ansicht an den nächsten Haupt-Thread-Aufruf zu senden:
Hinweis: Der Fehler wird behoben, wenn die geladene Ansicht eine feste Höhe hat. Ich habe es nicht versucht, wenn die Höhe des Headers nur vom Inhalt abhängt.
EDIT:
Sie können eine sauberere Lösung für dieses Problem finden, indem Sie diese Funktion implementieren und aufrufen
viewDidLayoutSubviews
quelle
tableHeaderView
sind eine Art Buggy mit Autolayout. Es gibt einige Problemumgehungen wie diese. Aber da ich dies schrieb, ich habe eine bessere und sauberere Lösung hier stackoverflow.com/a/21099430/127493 durch den Aufruf seine- (void)sizeHeaderToFit
inviewDidLayoutSubviews
Code:
quelle
Mithilfe der systemLayoutSizeFittingSize- Methode können Sie Autolayout erhalten, um eine Größe bereitzustellen .
Sie können dies dann verwenden, um den Rahmen für Ihre Anwendung zu erstellen. Diese Technik funktioniert immer dann, wenn Sie die Größe einer Ansicht kennen müssen, die intern Autolayout verwendet.
Der Code in Swift sieht aus wie
Oder in Ziel-C
Es sollte auch beachtet werden, dass in diesem speziellen Fall das Überschreiben von requireConstraintBasedLayout in Ihrer Unterklasse dazu führt, dass ein Layoutdurchlauf ausgeführt wird. Die Ergebnisse dieses Layoutdurchlaufs werden jedoch ignoriert und der Systemrahmen auf die Breite von tableView und 0 height gesetzt.
quelle
Folgendes hat bei mir funktioniert.
UIView
als Kopfansicht.UIView
Der Hauptvorteil, den ich sehe, ist die Begrenzung der Rahmenberechnungen. Apple sollte die
UITableView
API wirklich aktualisieren , um dies zu vereinfachen.Beispiel mit SnapKit:
quelle
Seltsame Dinge passieren. systemLayoutSizeFittingSize funktioniert hervorragend für iOS9, in meinem Fall jedoch nicht für iOS 8. Dieses Problem lässt sich also ganz einfach lösen. Holen Sie sich einfach den Link zur Unteransicht in der Kopfzeile und in viewDidLayoutSubviews, nachdem die Kopfansicht der Super-Call-Aktualisierung begrenzt ist, indem Sie die Höhe als CGRectGetMaxY (yourview.frame) + padding einfügen
UPD: Die einfachste Lösung aller Zeiten : Platzieren Sie in der Kopfansicht die Unteransicht und heften Sie sie nach links , rechts und oben . Platzieren Sie in dieser Unteransicht Ihre Unteransichten mit Einschränkungen für die automatische Höhe. Geben Sie danach den gesamten Auftrag für das Autolayout ab (keine Berechnung erforderlich).
Infolgedessen wird die Unteransicht wie gewünscht erweitert / verkleinert und am Ende viewDidLayoutSubviews aufgerufen. Zu diesem Zeitpunkt kennen wir die tatsächliche Größe der Ansicht. Legen Sie daher die Höhe der Header-Ansicht fest und aktualisieren Sie sie durch erneutes Zuweisen. Klappt wunderbar!
Funktioniert auch für die Fußzeilenansicht.
quelle
Erweiterte diese Lösung http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/ für die Tabellenfußansicht:
quelle
self.tableFooterView.transform
Teil erklären ? Warum ist es notwendig?Aktualisiert für Swift 4.2
quelle
Sie können eine obere + horizontale Positionsbeschränkung zwischen Kopfzeile und Tabellenansicht hinzufügen, um sie korrekt zu platzieren (wenn die Kopfzeile selbst alle erforderlichen internen Layoutbeschränkungen enthält, um einen korrekten Rahmen zu erhalten).
in der tableViewController viewDidLoad-Methode
quelle
Meine Tabellenkopfansicht ist eine UIView-Unterklasse. Ich habe im Initialisierer eine einzelne contentView-UIView erstellt, deren Grenzen mit dem Rahmen der Tabellenkopfansicht übereinstimmen, und alle meine Objekte als Unteransicht hinzugefügt.
Fügen Sie dann die Einschränkungen für Ihre Objekte in der
layoutSubviews
Methode der Tabellenkopfansicht und nicht im Initialisierer hinzu. Das hat den Absturz gelöst.quelle
Mein AutoLayout funktioniert sehr gut:
quelle
In den meisten Fällen besteht die beste Lösung einfach darin, das Framework nicht zu bekämpfen und Autoresizing-Masken zu verwenden:
Durch die Verwendung von Masken zur automatischen Größenänderung teilen Sie dem Framework mit, wie Ihre Ansicht ihre Größe ändern soll, wenn die Größe der Übersicht geändert wird. Diese Änderung basiert jedoch auf dem von Ihnen festgelegten Anfangsrahmen.
quelle
Ich weiß, dass dies ein alter Beitrag ist, aber nachdem ich alle diesbezüglichen SO-Beiträge durchgesehen und einen ganzen Nachmittag damit verbracht hatte, habe ich endlich eine saubere und doch sehr einfache Lösung gefunden
Zunächst sieht meine Ansichtshierarchie folgendermaßen aus:
tableHeaderView
Jetzt in der Ansicht (Nr. 3) habe ich alle Einschränkungen so eingerichtet, wie ich es normalerweise tun würde, einschließlich des unteren Bereichs zum Container. Dadurch wird die Größe des Containers (dh 3.View, dh HeaderView) basierend auf seinen Unteransichten und deren Einschränkungen angepasst.
Danach setze ich die Einschränkungen zwischen
3. View
und2. View
auf diese:Beachten Sie, dass ich den unteren Bereich absichtlich weglasse.
Sobald dies alles im Storyboard erledigt ist, müssen Sie nur noch diese drei Codezeilen einfügen:
quelle
Tipps: Wenn Sie die Methode setAndLayoutTableHeaderView verwenden, sollten Sie den Frame der Unteransichten aktualisieren. In dieser Situation sollte UILabels PreferredMaxLayoutWidth vor dem Aufruf von systemLayoutSizeFittingSize aufgerufen werden. Rufen Sie nicht layoutSubview auf.
Code anzeigen
quelle
Teile meinen Ansatz.
UITableView+XXXAdditions.m
Verwendung.
quelle
In meinem Fall hat die Methode mit systemLayoutSizeFittingSize aus irgendeinem Grund nicht funktioniert. Was für mich funktioniert hat, ist eine Modifikation der von HotJard veröffentlichten Lösung (seine ursprüngliche Lösung hat in meinem Fall auch unter iOS 8 nicht funktioniert). Was ich tun musste, war in der Kopfansicht eine Unteransicht zu platzieren und sie nach links, rechts, oben zu heften (nicht nach unten zu pinnen). Fügen Sie alles mit Autolayout in diese Unteransicht ein und tun Sie dies im Code:
quelle
Ein alter Beitrag. Aber ein guter Beitrag. Hier sind meine 2 Cent.
Stellen Sie zunächst sicher, dass in Ihrer Header-Ansicht die Einschränkungen so angeordnet sind, dass sie die eigene intrinsische Inhaltsgröße unterstützen. Dann machen Sie folgendes.
quelle
Ich konnte es durch den folgenden Ansatz erreichen (dies funktioniert für die Fußzeile auf die gleiche Weise).
Zunächst benötigen Sie eine kleine
UITableView
Erweiterung:Swift 3
In Ihrer Ansicht Controller-Klassenimplementierung:
Hinweise zur
UIView
Subview-Implementierung eines Headers :Sie müssen 100% sicher sein, dass Ihre Header-Ansicht das richtige Autolayout-Setup hat. Ich würde empfehlen, mit einer einfachen Header-Ansicht mit nur einer hohen Einschränkung zu beginnen und das obige Setup auszuprobieren.
Überschreiben
requiresConstraintBasedLayout
und zurücktrue
:.
quelle
Für Xamarin-Benutzer:
Angenommen, Sie haben die Header-Ansicht Ihrer Tabellenansicht als TableviewHeader bezeichnet
quelle
Hier ist, wie Sie in Ihrem tun können
UIViewController
quelle
Jede auf Einschränkungen basierende
UIView
kann gut seintableHeaderView
.Man muss ein
tableFooterView
vorher setzen und dann zusätzliche nachfolgende Einschränkungen fürtableFooterView
und auferlegentableHeaderView
.}}
Alle Details und Codefragmente finden Sie hier
quelle
Ich habe eine Problemumgehung gefunden. Wickeln Sie Ihre Autibayout-XIB-Header-Ansicht in einen leeren Uiview-Wrapper und weisen Sie die Header-Ansicht der tableViewHeader-Eigenschaft von tableView zu.
quelle
Folgendes funktioniert für UITableViewController in iOS 12:
Zeichnen Sie eine UIView in die Tabellenansicht über allen Prototypzellen für die Kopfzeile und unter allen Prototypzellen für die Fußzeile. Richten Sie Ihre Kopf- und Fußzeile nach Bedarf ein. Legen Sie alle erforderlichen Einschränkungen fest.
Verwenden Sie nun die folgenden Erweiterungsmethoden
und rufen Sie es in ViewDidLayoutSubviews der Unterklasse von UITableViewController auf
quelle
Ich bin auf das Problem gestoßen, die Breite 375pt zu erhalten. Die einzige Möglichkeit, die für mich funktioniert hat, besteht darin, die tableView weiterzuleiten, um die richtige Breite zu erhalten. Ich habe auch AutoLayout der Einstellung der Rahmengröße vorgezogen.
Hier ist die Version, die für mich funktioniert:
Xamarin.iOS
Schnelle Version (geändert von @Ben Packard Antwort)
quelle
Ich habe eine Unterklasse von erstellt
UITableView
und sowohlUIStackView
für die Kopf- als auch für die Fußzeile verwendet. Außerdem können mehrere Ansichten festgelegt werden.https://github.com/omaralbeik/StackableTableView
quelle
Meine Lösung besteht darin, eine neue Klasse wie diese zu erstellen.
Um es zu verwenden, fügen Sie einfach alle Ihre Unteransichten zu einer Instanz von hinzu
BaseTableHeaderView
und hängen Sie sie an Ihre Tabellenansicht an.Die Größe wird automatisch basierend auf den Einschränkungen geändert.
quelle
Akzeptierte Antworten sind nur für Tabellen mit einem einzelnen Abschnitt nützlich.
UITableView
StellenUITableViewHeaderFooterView
Sie für mehrere Abschnitte sicher, dass Ihr Header von erbt und es Ihnen gut geht.Als Alternative einbetten können Sie den aktuellen Header in der
contentView
von einemUITableViewHeaderFooterView
. Genau wieUITableViewCell
funktioniert.quelle
tableHeaderView
nicht die Abschnittsüberschrift.