2016-07-14 4 views
16

Diese Frage streng etwa ist iOS9 +In 7.3/9/2 + Wie kann ich die Rotationsanimation deaktivieren, wenn sich das Gerät dreht?

Sagen Sie bitte eine gewöhnliche moderne app (automatisches Layout, Storyboard, universal), die alle Positionen vier Dreh erlaubt

enter image description here

Sie wollen, dass es in der Normalen autorotate Weg, so wird es zu Ihrem neuen Constraint-basierten Layouts, wenn Benutzer Gerät von Querformat zu Hochformat dreht

Aber Sie wollen einfach keine Animation während der Benutzer das Gerät drehen. Sie möchten, dass es nur auf das neue seitliche oder aufrechte Layout "klickt".

Der einzige Weg, ich in der Lage gewesen, dies zu erreichen, ist durch Zugabe von:

override func viewWillTransitionToSize(size:CGSize, 
     withTransitionCoordinator coordinator:UIViewControllerTransitionCoordinator) 
    { 
    coordinator.animateAlongsideTransition(nil, completion: 
     {_ in 
     UIView.setAnimationsEnabled(true) 
     }) 
    UIView.setAnimationsEnabled(false) 
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator); 
    } 

zu einem View-Controller, ein höchsten oder nahezu höchsten VC, die den Rest der Behälter Ansichten oder was auch immer halten in die Szene.

Dies ist im Grunde die gleiche alte Idee der Verwendung von willRotateToInterfaceOrientation/didRotateFromInterfaceOrientation (beide jetzt in modernen iOS unbrauchbar), um Animationen ein- und auszuschalten.

Allerdings gibt es viele Probleme

  • dies nicht AppWide arbeiten, es ist ein Chaos, ist es szenenbasierte

  • es Very Bad scheint alle Animationen einfach zu deaktivieren

  • können Sie alle Arten von Rennstrecke sehen

Diese Frage ist streng genommen über iOS9 +

In diesen Tagen Gibt es einen besseren Weg, um die Drehung Animationen in einer App, die Landschaft/Porträt unterstützt zu deaktivieren?

Diese Frage ist streng über iOS9 +

+2

Für welche Version von iOS ist das gedacht? –

+0

Hallo @LukeVanIn danke, sicherlich iOS9. Beachten Sie den ersten Satz! – Fattie

+0

Funktioniert auf dem Simulator, aber nicht auf einem echten Gerät (ipad). 'UIView.areAnimationsEnabled()' gibt 'true' innerhalb des Animationsblocks zurück, was mich verwirrt (da es vorher deaktiviert wurde). Es muss ein Timing-Problem mit dem Rotationsanimationsblock bestehen ... ('setAnimationsEnabled' doc states:" _ Diese Methode betrifft nur die Animationen, die nach dem Aufruf übergeben werden. Wenn Sie diese Methode aufrufen, während vorhandene Animationen ausgeführt werden, werden diese Animationen fortgesetzt laufen lassen, bis sie ihren natürlichen Endpunkt erreichen._ ") – lazi74

Antwort

5

Sie können Methode swizzling verwenden.

Dies bedeutet, dass Sie Aufrufe von "viewWillTransitionToSize" auf jedem View-Controller in Ihrer Anwendung ändern, um stattdessen "genericViewWillTransitionToSize" aufzurufen.
Auf diese Weise müssen Sie keine Unterklasse oder wiederholten Code über Ihre Anwendung verwenden.

Mit diesem traurig, sollten Sie sehr vorsichtig mit swizzling sein, mit großer Macht kommt große Verantwortung. Stellen Sie die Klasse an einen Ort, an dem Sie oder der nächste Programmierer nach Ihnen wissen, wie Sie ihn finden, wenn er die Rotationsanimationen an die Controller zurückgeben möchte.

extension UIViewController { 

    public override static func initialize() { 
     struct Static { 
      static var token: dispatch_once_t = 0 
     } 

     dispatch_once(&Static.token) { 
      let originalSelector = #selector(UIViewController.viewWillTransitionToSize(_:withTransitionCoordinator:)) 
      let swizzledSelector = #selector(UIViewController.genericViewWillTransitionToSize(_:withTransitionCoordinator:)) 

      let originalMethod = class_getInstanceMethod(self, originalSelector) 
      let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) 

      let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) 

      if didAddMethod { 
       class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) 
      } else { 
       method_exchangeImplementations(originalMethod, swizzledMethod); 
      } 
     } 
    } 

    // MARK: - Method Swizzling 
    func genericViewWillTransitionToSize(size:CGSize, 
              withTransitionCoordinator coordinator:UIViewControllerTransitionCoordinator) 
    { 
     self.genericViewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 
     coordinator.animateAlongsideTransition(nil, completion: 
      {_ in 
       UIView.setAnimationsEnabled(true) 
     }) 
     UIView.setAnimationsEnabled(false) 
    } 
} 
+0

Tiger-Codierung ... – Fattie

+0

Dies ist die richtige Antwort :) – Ori

+0

Dieser arbeitete für Ich –

5

Soweit ich weiß, gibt es keinen besseren Weg, es zu tun.

Obwohl Sie eine separate Klasse mit dieser Methode deklarieren können und alle View-Controller in Ihrer App seine Unterklassen machen.

class NoRotateAnimationVC: UIViewController { 
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 
     super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 
     UIView.setAnimationsEnabled(false) 
     coordinator.notifyWhenInteractionEndsUsingBlock {_ in UIView.setAnimationsEnabled(true)} 
    } 
} 

Wenn Sie das Gerät drehen, alle View-Controller, der Ansichten benötigen, um ihre Größen erhalten viewWillTransitionToSize Methodenaufruf zu ändern.

Sie müssen diese neue Klasse einmal in Ihrer App deklarieren und dann alle Ihre View Controller-Deklarationen von der Klasse MyViewController: UIViewController in MyViewController: NoRotateAnimationVC ändern.

Die bereitgestellte Implementierung deaktiviert alle Animationen und aktiviert sie nach dem Übergang wieder. Wenn Sie diese Methode in nur einem View-Controller überschreiben, wird die Rotationsanimation überall deaktiviert, solange die Größe der Ansicht infolge einer Drehung geändert wird. Wenn dieser Ansichts-Controller jedoch nicht aktiv ist, werden Animationen nicht deaktiviert.

+0

Sie müssen diese neue Klasse einmal in Ihrer App deklarieren und dann alle Ihre View-Controller-Deklarationen von' class MyViewController: UIViewController {...} 'nach' MyViewController: NoRotateAnimationVC { ...} ' – bzz

+0

Ah, Sie sagen, dass jeder View-Controller dies tun muss. Meinetwegen. Interessanterweise habe ich festgestellt, dass wenn Sie nur einen auswählen - ich denke sogar zufällig - es funktioniert. (Ich habe keine Ahnung, ob das weitere Probleme verursachen könnte.) Danke nochmals – Fattie

+1

@JoeBlow Wenn Sie das Gerät drehen, erhalten alle View-Controller, deren Ansichten ihre Größe ändern müssen, den Methodenaufruf 'viewWillTransitionToSize'. Die bereitgestellte Implementierung deaktiviert alle Animationen und aktiviert sie nach dem Übergang wieder. Wenn Sie diese Methode in nur einem View-Controller überschreiben, wird die Rotationsanimation überall deaktiviert, solange die Größe der Ansicht infolge einer Drehung geändert wird. Wenn dieser Ansichts-Controller jedoch nicht aktiv ist, werden Animationen nicht deaktiviert. – bzz

Verwandte Themen