Ich habe einen View-Controller mit einem Child-View-Controller.
%Vor%A sollte gezwungen werden, immer im Portrait zu bleiben, aber B sollte sich frei drehen können.
Ich weiß, dass shouldAutorotate
für alle View-Controller und ihre Kinder gilt, aber gibt es eine Möglichkeit, dies zu umgehen? Es scheint, als könnte ich shouldAutorotateToInterfaceOrientation
verwenden, aber das ist in iOS 8 blockiert.
Ich möchte einen Videoplayer statisch halten (horizontale Videos sind unabhängig von der Ausrichtung des Geräts immer horizontal), während das Overview-Overlay der Steuerschicht frei rotieren darf.
Ich benutze Swift.
Ich hatte genau dieses Problem und fand schnell heraus, dass es eine Menge schlechter Ratschläge bezüglich Autorotation gibt, besonders weil iOS 8 anders damit umgeht als frühere Versionen.
Zunächst möchten Sie nicht eine Gegenrotation manuell anwenden oder UIDevice
-Orientierungsänderungen abonnieren. Eine Gegenrotation führt immer noch zu einer unschönen Animation, und die Ausrichtung Gerät entspricht nicht immer der Ausrichtung Schnittstelle . Im Idealfall möchten Sie, dass die Vorschau der Kamera wirklich eingefroren bleibt und die Benutzeroberfläche der App der Ausrichtung und Größe der Statusleiste bei ihrer Änderung entspricht, genau wie die native Kamera-App.
Während einer Orientierungsänderung in iOS 8 rotiert das Fenster selbst und nicht die darin enthaltenen Ansichten. Sie können die Ansichten mehrerer View-Controller zu einem einzelnen UIWindow
hinzufügen, aber nur der rootViewController
erhält eine Möglichkeit, über shouldAutorotate()
zu antworten. Obwohl Sie die Rotationsentscheidung auf der Ebene des Ansichtscontrollers treffen, dreht sich tatsächlich das übergeordnete Fenster, wodurch alle Unteransichten (einschließlich der Ansichten anderer Ansichtscontroller) gedreht werden.
Die Lösung besteht aus zwei UIWindow
, die übereinander gestapelt sind und sich jeweils mit einem eigenen Root-View-Controller drehen (oder nicht). Die meisten Apps haben nur eine, aber es gibt keinen Grund, warum du nicht zwei haben und sie wie jede andere UIView
-Unterklasse überlagern kannst.
Hier ist ein funktionierender Proof-of-Concept, den ich hier ebenfalls auf GitHub gesetzt habe . Ihr spezieller Fall ist etwas komplizierter, weil Sie einen Stapel mit View-Controllern haben, aber die Grundidee ist dieselbe. Ich werde auf einige spezifische Punkte unten eingehen.
%Vor% Wenn Sie einen negativen Inset auf interfaceWindow
setzen, wird die schwarze rechteckige Maske, die Sie sonst sehen würden, etwas größer als die Bildschirmgrenzen. Normalerweise würden Sie das nicht bemerken, weil sich die Maske mit dem Fenster dreht, aber da das Kamerafenster fixiert ist, wird die Maske während der Drehung in den Ecken sichtbar.
Genau das, was Sie hier erwarten würden, fügen Sie einfach Ihr eigenes Setup für AVCapturePreviewLayer
hinzu.
Der letzte Trick ist das Rückgängigmachen des negativen Einschubs, den wir auf das Fenster angewendet haben, was wir erreichen, indem wir view
um den gleichen Betrag versetzen und contentView
als Hauptansicht behandeln.
Für Ihre App wäre interfaceWindow.rootViewController
Ihr Tab-Bar-Controller, der wiederum einen Navigations-Controller usw. enthält. Alle diese Ansichten müssen transparent sein, wenn Ihr Kamera-Controller erscheint, damit das Kamera-Fenster darunter durchscheinen kann. Aus Performance-Gründen sollten Sie sie undurchsichtig lassen und nur dann alles transparent machen, wenn die Kamera tatsächlich verwendet wird, und das Kamerafenster auf hidden
stellen, wenn dies nicht der Fall ist (und gleichzeitig die Aufnahmesitzung beenden).
Es tut mir leid, einen Roman zu veröffentlichen; Ich habe das nirgendwo anders gesehen gesehen und es hat eine Weile gedauert, bis ich herausgefunden habe, hoffentlich hilft es dir und allen anderen, die versuchen, das gleiche Verhalten zu bekommen. Selbst Apples AVCam
Beispiel-App geht damit nicht richtig um.
Das Beispiel-Repo, das ich gepostet habe , enthält auch eine Version, bei der die Kamera bereits eingerichtet ist. Viel Glück!
Kurze Antwort: Nein, alle sichtbaren Controller und Ansichten rotieren (oder rotieren nicht) zusammen.
Lange Antwort:
Zuerst müssen Sie Autorotate-Entscheidungsfunktionen im Stammcontroller implementieren. das kann bedeuten, eine Nav-Controller-Unterklasse zu erstellen.
Sie können Ihr gewünschtes Verhalten hacken, indem Sie die Elternansicht automatisch drehen lassen - aber Sie müssen es manuell drehen zurück , um nicht gedreht zu erscheinen.
Oder Sie können nicht automatisch eine automatische Drehauswahl durchführen, sondern auf Benachrichtigungen achten, die das physische Gerät gedreht hat, und die gewünschten Ansichten manuell drehen, zB: Replizierung der Kamera-App-Rotation auf Landschaft IOS 6 iPhone
Siehe auch, fyi:
Erzwingen, dass ein UIViewController zu Portrait wird Orientierung in iOS 6
shouldAutoRotate-Methode, die in iOS6 nicht aufgerufen wird
Wie die UIViewController-Rotation als Reaktion auf die Ausrichtung implementiert wird Änderungen?
Die einfachste und geradlinigste Antwort auf diese Frage ist die Betrachtung von Apples AVCam Beispiel Code. Die wichtigsten Teile für mich waren, dass es:
layerClass
AVCaptureVideoPreviewLayer
ist. videoOrientation
der AVCaptureVideoPreviewLayer-Verbindung auf die statusBarOrientation
der Anwendung, wenn die Ansicht angezeigt wird, im Wesentlichen viewWillAppear(_:)
. videoOrientation
auf UIDevice.currentDevice().orientation
in viewWillTransitionToSize(_:withTransitionCoordinator:)
. Ich habe den von jstn beschriebenen Ansatz des Hintergrundfensters implementiert und es hat ziemlich gut funktioniert, aber in Wirklichkeit ist es viel komplizierter als nötig. AVCam funktioniert gut und hat einen relativ einfachen Ansatz.
Tags und Links ios swift uiviewcontroller autorotate