Ich habe einen View-Controller, in dem ich bestimmte Subviews, Labels etc. ausblenden möchte, je nachdem, was die Merkmalssammlung ist. Zum Beispiel habe ich Etiketten auf der Seite, die ich verstecken möchte, wenn horizontal kompakt, und Etiketten auf der oberen und unteren Seite, die ich ausblenden möchte, wenn sie vertikal kompakt.UIStackView Versteckte Ansichten und unerfüllbares Layout bei Drehung
Da ich ganze Abschnitte der Schnittstelle ausblenden möchte, klingt es wie ein UIStackView würde es einfacher machen. Ebenso versuche ich so viel wie möglich in Interface Builder/Xcode (9.1 9B55) anstatt in Code zu tun, um es einfach zu halten.
Das Hauptelement des Entwurfs ist ein Schachbrett, das:
- Ist immer Seitenverhältnis 1: 1
- ist so groß wie möglich innerhalb der Ansicht
Dann Etiketten und andere Gegenstände um sie herum möchte ich bewegen und verstecken, basierend auf der aktuellen Merkmalssammlung.
Ich habe damit begonnen, eine horizontale Stapelansicht, Ausrichtung und Verteilung auf "Fill" zu erstellen. Darin befinden sich zwei Elemente, BoardView (lila) und LabelView (gelb).
Das labelView enthält einige Beschriftungen, wobei in der Ansicht selbst Einschränkungen für das Layout dieser Beschriftungen festgelegt sind.
Die boardView hat eine Einschränkung des Seitenverhältnisses 1: 1 (@ 1000):
I setzte die folgenden Bedingungen für die Stack-Ansicht, um es in die Super Pinning (mit Ausnahme des unten) :
- Sicher Area.trailing = Stapel View.trailing (@ 1000)
- Sicher Area.leading = Stapel View.leading (@ 1000)
- Sicher Area.top = Stapel View.top (@ 1000)
- Sicher Area.bottom> = Stapel View.bottom (@ 1000)
ich diese Einschränkungen gesetzt die boardView nie überläuft die Superview zu versichern:
- boardView.width < = Sicher Area.width (@ 1000)
- boardView.height < = Sicher Area.height (@ 1000)
Und dann stelle ich diese Einschränkungen mit einer niedrigeren Priorität, so dass, wenn möglich, die Breite oder Höhe des Super zu füllen erweitern (aber nicht überlaufen, da diese eine geringere Priorität als oben sind):
- boardView. width = Sichere Area.width (@ 250)
- boardView.height = Sicher Area.height (@ 250)
Das alles scheint sehr gut zu funktionieren.Keine Fehler in Xcode und die App verhält, wie ich erwarten würde, im Hoch- und Quer (diese Screenshots von iPhone 8 Simulator):
Das Problem kommt, wenn ich versuche, die richtige Ansicht zu verbergen. Ich versuche dies zu tun, indem ich die namesView verberge, wenn wir uns vertikal im normalen Modus befinden. Ich nameView wählen, klicken Sie auf das + neben dem installierten Kontrollkästchen, wählen Sie hR:
Und dann deaktivieren Sie das installierte Box für hR:
Das sieht gut aus in Xcode. Keine Fehler und IB scheint zu zeigen, alle Ansichten, wie ich beide und Porträt erwarten würde in der Landschaft (wo die Namen Etiketten versteckt sind):
So weit, so gut. In der Tat, wenn ich es betreibe, sieht es zunächst so aus, wie wir es erwarten würden. Wenn wir den Simulator in der Landschaft starten, sieht es gut aus:
Wenn wir den Simulator im Portrait beginnen, sieht es gut aus:
Also, was ist das Problem? Nun, sobald wir von Hoch- auf Querformat drehen, ist das Layout völlig falsch:
Zur gleichen Zeit, wir in der Konsole erhalten einen LayoutConstraints Fehler:
2017-12-03 19:25:55.710381-0600 TestLayoutSIngleView[31439:3231004] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fixes it.
(
"<NSLayoutConstraint:0x60400009b8a0 UIView:0x7fe920603e90.width == UIView:0x7fe920603e90.height (active)>",
"<NSLayoutConstraint:0x60000009ced0 UIStackView:0x7fe92050bd70.leading == UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'.leading (active)>",
"<NSLayoutConstraint:0x60000009d100 UIStackView:0x7fe92050bd70.top == UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'.top (active)>",
"<NSLayoutConstraint:0x60000009d150 UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'.trailing == UIStackView:0x7fe92050bd70.trailing (active)>",
"<NSLayoutConstraint:0x60000009d1a0 UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'.bottom >= UIStackView:0x7fe92050bd70.bottom (active)>",
"<NSLayoutConstraint:0x60000009e5a0 'UISV-canvas-connection' UIStackView:0x7fe92050bd70.leading == UIView:0x7fe920603e90.leading (active)>",
"<NSLayoutConstraint:0x60000009ce30 'UISV-canvas-connection' UIStackView:0x7fe92050bd70.top == UIView:0x7fe920603e90.top (active)>",
"<NSLayoutConstraint:0x60000009e5f0 'UISV-canvas-connection' V:[UIView:0x7fe920603e90]-(0)-| (active, names: '|':UIStackView:0x7fe92050bd70)>",
"<NSLayoutConstraint:0x60000009cde0 'UISV-canvas-connection' H:[UIView:0x7fe920603e90]-(0)-| (active, names: '|':UIStackView:0x7fe92050bd70)>",
"<NSLayoutConstraint:0x60000009e7d0 'UIView-Encapsulated-Layout-Height' UIView:0x7fe92050b8f0.height == 375 (active)>",
"<NSLayoutConstraint:0x60000009e780 'UIView-Encapsulated-Layout-Width' UIView:0x7fe92050b8f0.width == 667 (active)>",
"<NSLayoutConstraint:0x60000009d060 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide']-(0)-| (active, names: '|':UIView:0x7fe92050b8f0)>",
"<NSLayoutConstraint:0x60000009d010 'UIViewSafeAreaLayoutGuide-left' H:|-(0)-[UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'](LTR) (active, names: '|':UIView:0x7fe92050b8f0)>",
"<NSLayoutConstraint:0x60000009d0b0 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide']-(0)-|(LTR) (active, names: '|':UIView:0x7fe92050b8f0)>",
"<NSLayoutConstraint:0x60000009cfc0 'UIViewSafeAreaLayoutGuide-top' V:|-(0)-[UILayoutGuide:0x6000001b5d20'UIViewSafeAreaLayoutGuide'] (active, names: '|':UIView:0x7fe92050b8f0)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60400009b8a0 UIView:0x7fe920603e90.width == UIView:0x7fe920603e90.height (active)>
Ich mag die Idee, UIStackView zu verwenden, um Auto-Layout zu erleichtern und Ansichten zu verstecken. Aber wenn das, was ich in Xcode sehe, nicht funktioniert, wenn es kompiliert und ausgeführt wird, scheint es, als würde das schwierig werden.
Was mache ich falsch (oder laufe ich in einen Xcode-Fehler)?
Ich habe ein GitHub Projekt, das die oben zeigt: https://github.com/johnstewart/TestLayoutSIngleView
bearbeiten .... Es fällt mir ein, wie ich alle oben genannten Schreiben fertig sind, dass, wenn wir diese Ansicht in der Landschaft verstecken Modus, das Layout wäre nicht befriedigend ... aber ich verstecke diese Ansicht nicht in Landschaft, nur Porträt. Aus irgendeinem Grund führt iOS die Änderung des Layouts VOR der Rotation durch.
Wenn ich die Priorität dieser 1000-750 gesetzt:
- Sicher Area.trailing = Stapel View.trailing (@ 1000)
... Ich kapier nicht automatische Layoutfehler auf der Konsole Allerdings hat die einmal gedrehte Landschaftsansicht gar nichts am richtigen Ort.
Es ist, als ob die Stapelansicht sofort beginnen, um die Drehung von Hoch- auf Querformat geschrumpft ist, und in diesem geschrumpften Zustand nach Beendigung der Drehung die Stapelansicht zu verlassen, auch wenn es jetzt es vielen Platz:
ich hoffe, ich etwas offensichtlich hier bin fehlt ... sonst sehe ich nicht, wie un-Installation Ansichten basierend auf Charakterzug Sammlungen mit UIStackView überhaupt machbar ist; dies scheint wie ein einfaches Beispiel (und es ist, ich viel mehr Material hinzuzufügen habe!)
Edit:
Das WWDC Video, wo ich diese Technik sah aus WWDC2017 ist, Techniques Auto-Layout in Schnittstelle Builder (https://developer.apple.com/videos/play/wwdc2017/412/). Die Demo hierfür beginnt um 29:00 Uhr.
Ich war falsch, aber es war die "Installierte" Eigenschaft, die dafür verwendet wurde. Wie die angenommene Antwort zeigt, war "Versteckt" der Weg, dies zu tun.
aktualisieren 20.171.205 - Aktualisiert Xcode 9.2 (9C40b) und es ist die gleiches Verhalten. –