2012-12-06 3 views
44

Ich möchte die Layout-Einschränkungen ändern, wenn das Gerät dreht. Meine UIViewController besteht aus 2 UIViews, in Landschaft sind sie horizontal ausgerichtet, und im Hochformat sind sie vertikal ausgerichtet.iOS Auto-Layout-Einschränkungen ändern, wenn Gerät dreht

Es ist tatsächlich Arbeit, in willAnimateRotationToInterfaceOrientation ich die gewünschten Einschränkungen zu entfernen und ersetzte sie mit anderen das Recht Layout haben ...

Aber es gibt Probleme, beginnt während der Rotation Auto Layout vor willAnimateRotationToInterfaceOrientation Einschränkungen brechen genannt wird Wo sollen wir unsere Einschränkungen bei der Neuausrichtung des Geräts ersetzen?

Ein weiteres Problem ist die Leistung, nach ein paar Umdrehungen das System nicht mehr Zwänge nicht bricht, aber ich habe einen großen Leistungsabfall, vor allem im Portrait-Modus ...

+0

Bitte fügen Sie Ihren Code hier –

+0

@ Makleesh: Ja, Sie haben Recht, eine Menge Probleme entstehen bei der Verwendung von Auto-Layout, aber ich finde sie ziemlich handlich .. sowieso, sieht es wird die neue Art, Dinge zu tun, besser zu bekommen hinein jetzt als spät. – vitaminwater

+0

@Waseem: Ich habe wirklich keinen Code zum Posten ... wie gesagt, die Einschränkungen sind bereits gebrochen, bevor mein Code ausgeführt wird, also weiß ich nicht wirklich, welchen Code ich schreiben könnte! – vitaminwater

Antwort

49

In willRotateToInterfaceOrientation:duration:, senden Sie setNeedsUpdateConstraints an jede Ansicht, die ihre Einschränkungen geändert benötigt.

Alternativ können Sie auch eine UIView Unterklasse erstellen. Melden Sie sich in Ihrer Unterklasse an, um UIApplicationWillChangeStatusBarOrientationNotification zu erhalten.Wenn Sie die Benachrichtigung erhalten, senden Sie sich setNeedsUpdateConstraints.

Dies setzt das Flag needsUpdateConstraints in der Ansicht. Bevor das System Layout ausführt (durch Senden von layoutSubviews Nachrichten), sendet es eine updateConstraints Nachricht an jede Ansicht, die das needsUpdateConstraints-Flag festgelegt hat. Hier sollten Sie Ihre Einschränkungen ändern. Machen Sie eine UIView Unterklasse und überschreiben Sie updateConstraints, um Ihre Einschränkungen zu aktualisieren.

+0

Das ist sehr cool und funktioniert einwandfrei. In meiner Implementierung iteriere ich über [view constraints] und entferne jedes einzelne, bevor ich die orientierungsspezifischen Einschränkungen hinzufüge. Dies ist ein Großhandelstausch und die animierte Änderung sieht gut aus. –

+2

Müssen Sie jede Ansicht untergliedern, bei der die Randbedingungen geändert werden, oder können Sie das vollständig vom View-Controller aus tun? Es scheint, dass eine sehr, sehr häufige Situation sein würde, einige Breiten und Höhen für Rotationsänderungen zu ändern, aber wäre ziemlich hässlich, wenn Sie Ihr Layout mit mehreren benutzerdefinierten Klassen für viele Innenansichten ausfüllen müssen. – Tenfour04

+1

Sie können eine benutzerdefinierte Klasse für die Top-Level-Ansicht erstellen und allen Subviews, die geänderte Einschränkungen benötigen, Outlets zuweisen. Dann können Sie alle Einschränkungen in der Methode 'updateConstraints' dieser benutzerdefinierten Klasse einrichten. –

2

Überschreibung -(void) viewWillLayoutSubviews in Ihrem UIViewController Ihre Zwänge zu aktualisieren wie unten Code:

-(void) viewWillLayoutSubviews { 
    switch(self.interfaceorientation) 
    { 
      case UIInterfaceOrientationLandscapeLeft: 

       break; 
      case UIInterfaceOrientationLandscapeRight: 

       break; 

      case UIDeviceOrientationPortrait: 

       break; 

      case UIDeviceOrientationPortraitUpsideDown: 

       break; 

    } 
} 
+0

layoutSubviews ist eine UIView-Methode, nicht sicher, dass es der richtige Weg ist, aber danke! Dieses Projekt wurde jetzt ausgeliefert, so dass ich es nicht wirklich testen kann, der nächste Ansatz zu dem, was Sie vorschlagen, wäre die ViewWillLayoutSubviews von der UIViewController zu verwenden, ich glaube, ich hatte das ohne Erfolg versucht .. – vitaminwater

+2

Sie müssen '[super layoutSubviews]' aufrufen, wenn Sie das automatische Layout verwenden. Zweitens möchten Sie Ihre Integritätsbedingungen nicht in 'layoutSubviews' ändern, da 'layoutSubviews' gesendet wird ** nachdem ** das System die Einschränkungen gelöst hat. Wenn Sie hier die Einschränkungen ändern, wird beim nächsten Durchlauf der Laufschleife ein anderer Layout-Durchlauf ausgelöst (um die neuen Bedingungen zu lösen). –

+0

Sieht aus, als wäre die korrekte Methode zum Implementieren/Überschreiben hier 'viewWillLayoutSubviews'. –

13

Es gibt sehr gute Erklärung von Auto-Layout und Rotationen in Matthijs Hollemans Post. Sie können es hier finden: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

Normalerweise benötigen Sie etwa 4 Einschränkungen, um Ihre Sicht richtig zu positionieren. Wenn meine Ansichten konstante Größe haben, bevorzuge ich Höhe und Breite. Danach können Sie Leading und Top Space Constraints verwenden, um zu tun, was Sie wollen. Zum Beispiel können Sie IBOutlets für führende und Top-Platzbeschränkungen für Ihre Ansichten einstellen:

@interface ViewController : UIViewController { 
    IBOutlet NSLayoutConstraint *_leadingSpaceConstraint; 
    IBOutlet NSLayoutConstraint *_topSpaceConstraint; 
} 

Dann steuern Ziehen aus der Steckdose zu Ihrer Einschränkung. Jetzt können Sie direkt Ihre Ansicht Einschränkung von Code ändern:

_leadingSpaceConstraint.constant = NEW_CONSTRAINT_VALUE; 

Um die Änderungen verpflichten Sie rufen müssen:

[self.view layoutIfNeeded]; 

Und wenn Sie es tun wollen animiert:

[UIView animateWithDuration:0.25 
       animations:^{ 
        [self.view layoutIfNeeded]; 
       }]; 

Ich denke, es wird in willAnateRotationToInterfaceOrientation funktionieren, weil Sie keine Einschränkungen mit diesem Ansatz brechen müssen.

Einige Beispiele: Sie haben zwei quadratische Ansichten im Hochformat, eine unter der anderen. Setzen Sie ihre Beschränkungen für "Leading Space to Superview" beispielsweise auf 20. Setzen Sie dann für die erste Ansicht "Obergrenze für Superview-Einschränkung" auf 20 und für Sekunde auf 120. Es wird unser Standard-Setup sein.

Dann müssen Sie nach der Rotation Ihre Einschränkungen neu berechnen. Setzen Sie nun beide oberen Einschränkungen auf 20 und die führenden Einschränkungen auf 20 bzw. 120. Dann commit Änderungen mit layoutIfNeeded.

Ich hoffe, es wird helfen.

+0

Ich habe das Gefühl, dass du den Zweck des automatischen Layouts vereitelst, wenn du eine feste Breite und Höhe festlegst und den oberen/linken Platz zum Positionieren hinzufügst, du tust nichts mehr als Feder und Streben. Natürlich gibt es keine Borken-Einschränkungen, da Sie keine Einschränkungen hinzufügen, die Ihre Ansichten miteinander verbinden. Wenn Sie beispielsweise mehr als eine Bildschirmgröße/-verhältnis verwalten müssen, müssen Sie spezielle Fälle erstellen, was durch das automatische Layout vermieden wird! – vitaminwater

+0

Ich denke, es ist nur der Sonderfall. Sie benötigen eine feste Größe und dynamische Position - Sie können es bekommen. Sie brauchen dynamische Größe - Sie können es auch bekommen. Auto-Layout ermöglicht es Ihnen, Dynamik wann und wo Sie wollen zu implementieren. Feder und Streben - nicht. – Flar

+0

Es gibt einige spezielle Fälle, in denen Sie einige fest codierte Größen mischen müssen, die auf Rotationen reagieren. Beispiel: In einer Bildlaufansicht, für die Paging aktiviert ist, müssen die inneren Ansichten die gleiche Breite wie der Bildschirm haben, damit sie beim Seitenwechsel mit dem Bildschirm ausgerichtet werden. Es lohnt sich nicht, das automatische Layout auszuschalten, solange es einen solchen Workaround gibt. Auto-Layout ist eine große Zeitersparnis bei der Unterstützung der verschiedenen Geräteauflösungen und es ist wahrscheinlich, dass zukünftige Geräte noch mehr Auflösungen unterstützen werden. – Tenfour04

Verwandte Themen