2017-12-04 12 views
3

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):

enter image description here

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):

enter image description here enter image description here

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:

enter image description here

Und dann deaktivieren Sie das installierte Box für hR:

enter image description here

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):

enter image description here enter image description here

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:

enter image description here

Wenn wir den Simulator im Portrait beginnen, sieht es gut aus:

enter image description here

Also, was ist das Problem? Nun, sobald wir von Hoch- auf Querformat drehen, ist das Layout völlig falsch:

enter image description here

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:

enter image description here

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.

+0

aktualisieren 20.171.205 - Aktualisiert Xcode 9.2 (9C40b) und es ist die gleiches Verhalten. –

Antwort

2

Ich denke, man kann erreichen, was Sie ohne ‚installiert‘ wollen Eigenschaft: gerade gesetzt ‚versteckt‘ für Portrait-Modus: enter image description here

enter image description here

+0

Ich habe versucht, damit ein bisschen zu spielen, und es löst nicht wirklich mein Problem. Wenn Sie die namesView für hR ausblenden, erhalten Sie Fehler bei den Einschränkungen für die Elemente in nameView. Sie können sie auch ausblenden, aber das scheint nicht zu skalieren, wenn das Layout komplexer ist als dieses (sehr minimalisierte) Beispiel. –

+0

Problem mit 'installierter' Eigenschaft ist, dass nach der 'Deinstallation' der Controller' leftView' nicht bekommen kann. Es wurde aus Superview entfernt und Controller konnte es nicht von Xib laden, da es nur am Anfang des VC-Lebenszyklus passiert. Lösung ist die Verwendung von Outlets für 'leftView' und' stackView' und das Aufrufen von '[self.stackView removeArrangedSubview: self.leftView];' und '[self.stackView addArrangedSubview: self.leftView];' 'viewWillTransitionToSize: withTransitionCoordinator:' Methode abhängig von der Bildschirmausrichtung. – Josshad

+0

Ich * schwöre * Ich sah diesen "installierten" Trick, um ein Stück eines UIStackView irgendwann in einem WWDC-Video zu verstecken, weshalb ich dachte, dass dies der "Apple-Weg" war, mit dem Entfernen von Ansichten in IB umzugehen. Ich habe alle WWDC-Videos durchgesehen, die ich in der Referenzstapelansicht finden kann, aber bisher finde ich sie nicht. –

Verwandte Themen