Ich versuche, eine Containeransicht mit einem Controller mit dynamischer Höhe in einer UIScrollView zu erstellen und deren Größe mithilfe des automatischen Layouts automatisch zu ändern.
View Controller A ist die Bildlaufansicht, in der die Containeransicht sowie weitere Inhalte enthalten sind.
View Controller B ist der View Controller, für den ich eine dynamische Größe haben möchte und bei dem der gesamte Inhalt in der Bildlaufansicht von View Controller A in voller Höhe angezeigt werden soll.
Ich habe einige Probleme damit, dass die dynamische Größe von B die Größe der Containeransicht in A automatisch festlegt. Wenn ich jedoch eine Höhenbeschränkung für die Containeransicht in A festlege ,
Es wäre die erwartete Ausgabe, wenn View Controller B auch eine Höhe von 250 hätte. Es funktioniert auch gut für Höhe 1000, soweit ich weiß, sind alle Einschränkungen für das automatische Layout ordnungsgemäß eingerichtet. Da die Höhe eigentlich dynamisch sein sollte, möchte ich leider vermeiden, überhaupt eine Höhenbeschränkung festzulegen.
Ich bin mir nicht sicher, ob es Einstellungen für View Controller BI gibt, mit denen die Größe je nach Inhalt automatisch aktualisiert werden kann, oder ob es andere Tricks gibt, die ich verpasst habe. Jede Hilfe wäre sehr dankbar!
Gibt es eine Möglichkeit, die Größe der Containeransicht in A entsprechend der Größe von View Controller B zu bestimmen, ohne eine Höhenbeschränkung festzulegen?
quelle
Antworten:
Ja, das gibt es. Ich habe es geschafft, dieses Verhalten in einem meiner eigenen Projekte zu erreichen.
Alles, was Sie tun müssen, ist dem System mitzuteilen, dass es keine Einschränkungen hinzufügen soll, die den festen Rahmensatz für Ihre Stammansicht in Interface Builder nachahmen. Der beste Ort, um dies zu tun, ist in Ihrem Container View Controller, wenn Ihr Embed-Segue ausgelöst wird:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // You might want to check if this is your embed segue here // in case there are other segues triggered from this view controller. segue.destinationViewController.view.translatesAutoresizingMaskIntoConstraints = NO; }
Wichtig:
Sie müssen sicherstellen, dass die Ansicht, die Sie in den Container laden, von oben nach unten eingeschränkt ist, und Sie müssen die Priorität einer der vertikalen Einschränkungen auf einen Wert unter 1000 festlegen. (Es wird empfohlen, immer die untere Einschränkung zu verwenden dafür.) Dies ist notwendig, weil sich Interface Builder sonst beschweren wird - aus gutem Grund:
Zur Entwurfszeit hat Ihre Stammansicht eine feste Größe (Höhe). Wenn nun alle Ihre Unteransichten eine feste Höhe haben und mit festen Einschränkungen verbunden sind, die alle dieselbe Priorität haben, können alle diese Anforderungen nur erfüllt werden, wenn die Höhe Ihrer festen Stammansicht zufällig genau der Gesamthöhe Ihrer Unteransichten und den vertikalen Einschränkungen entspricht. Wenn Sie die Priorität einer der Einschränkungen auf 999 Interface Builder senken, wissen Sie, welche Einschränkung aufgehoben werden muss. Zur Laufzeit jedoch - wenn die
translatesAutoresizingMaskIntoConstraints
Eigenschaft wie oben angegeben festgelegt ist - gibt es keinen festen Rahmen mehr für Ihre Stammansicht, und das System verwendet stattdessen Ihre 999-Prioritätsbeschränkung.quelle
Aus der Antwort von @Mischa konnte ich die Höhe einer containerView abhängig von ihrem Inhalt dynamisch machen:
Schreiben Sie im viewController der containerView:
override func loadView() { super.loadView() view.translatesAutoresizingMaskIntoConstraints = false }
Und achten Sie darauf, dass alle vertikalen Einschränkungen in IB festgelegt sind. Dazu müssen Sie view.translatesAutoresizingMaskIntoConstraints = false von außerhalb des View-Controllers nicht festlegen.
In meinem Fall habe ich versucht, die Größe des Containers in eine tableView im viewController zu ändern. Da die tableView abhängig von ihrer Übersicht eine flexible Höhe hat (also alles in Ordnung für IB), habe ich die vertikalen Einschränkungen im Code folgendermaßen abgeschlossen:
@IBOutlet private var tableView: UITableView! { didSet { tableView.addConstraint(tableViewHeight) } } private lazy var tableViewHeight: NSLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 0)
Beobachten Sie dann die contentSize-Höhe der Tabellenansicht und passen Sie die Konstante der tableViewHeight-Einschränkung bei Bedarf programmgesteuert an.
quelle
Swift 4, Xcode 9
Die akzeptierte Antwort allein hat das Problem für mich nicht gelöst.
Meine Hierarchie: ScrollView -> Inhaltsansicht (UIView) -> Ansichten | Containeransicht | Weitere Ansichten.
Ich musste die folgenden Einschränkungen hinzufügen, damit sich ScrollView und Container dynamisch anpassen:
view.translatesAutoresizingMaskIntoConstraints = false
entwederprepareForSegue()
oderloadView()
wie andere Antworten ein.Jetzt habe ich eine dynamisch anpassbare Containeransicht in einer Scroll-Ansicht mit automatischer Größenänderung.
quelle
Aufbauend auf der großartigen Lösung von @ Mischa für dieses Problem müssen Sie, wenn der Container eine UITableView mit dynamischer Größe einbettet, die Überschreibung von contentSize und intrinsicContentSize sowie die Einstellung
translatesAutoresizingMaskIntoConstraints = false
gemäß der akzeptierten Antwort prüfen .Wenn die übergeordnete Ansicht die Containeransicht lädt und einrichtet, wird die Eigenhöhe jeder der UITableViewCells auf 0 abgeleitet, daher die UITableViewDelegate-Methode von:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
wird nicht aufgerufen. Dadurch wird UITableView so angezeigt, als hätte es keinen Inhalt.
Wenn Sie die intrinsische Inhaltsgröße überschreiben, um die tatsächliche Inhaltsgröße zurückzugeben, wird die Tabellenansicht mit der Größe angezeigt, die für den Inhalt erforderlich ist.
Ein großartiger Artikel von Emilio Peláez geht näher auf dieses Thema ein.
quelle
Ich habe diese Lösung ausprobiert und für mich gearbeitet.
Versuchen Sie im Zielansichts-Controller (untergeordneter Ansicht) wie folgt, auf den übergeordneten Ansichts-Controller zuzugreifen:
if let parentVC = self.parent as? EmbededContinerViewController { if let myParent = parentVC.parent as? ParentViewController { myParent.subViewHeight.constant += 2000 myParent.subView.layoutIfNeeded() }
}}
Vielleicht ist dies keine normale Lösung, hat aber für mich funktioniert und mein Problem gelöst.
Ich habe diesen Code in Swift 5.1 ausprobiert .
quelle