2017-09-07 5 views
2

Ich habe eine benutzerdefinierte Ansicht Controller, die Vollbild mit einer Schaltfläche gehen kann. Es ist normalerweise eine Unteransicht einer Ansicht (eingebettet). Das ist mein aus einbetten Vollbild einzugeben:Choppy fullscreen exit Übergang

private func enterFullScreenFromEmbed() { 

    self.proxyView = UIView(frame: self.view.frame) 
    self.proxyView?.isHidden = true 
    self.proxyView?.autoresizingMask = self.view.autoresizingMask 
    self.view.superview?.addSubview(self.proxyView!) 

    // Now set the frame to the screen frame 
    let frame = self.view.window?.convert(self.view.frame, from: self.proxyView?.superview) 
    self.view.window?.addSubview(self.view) 
    self.view.frame = frame! 

    self.isFullscreen = true 

    UIView.animate(withDuration: 0.25) { 
     self.view.frame = self.view.window!.bounds 
     self.view.layoutIfNeeded() 
     self.setNeedsStatusBarAppearanceUpdate() 
    } 
} 

Und von Vollbild Verlassen:

private func exitFullScreenToEmbed() { 

    let frame = self.view.window?.convert(self.view.frame, to: self.proxyView?.superview) 
    self.proxyView?.superview?.addSubview(self.view) 
    self.view.frame = frame! 

    self.isFullscreen = false 

    UIView.animate(withDuration: 0.25, animations: { 

     self.view.frame = self.proxyView!.frame 

     self.view.layoutIfNeeded() 
     self.setNeedsStatusBarAppearanceUpdate() 
    }) { (_) in 
     self.proxyView?.removeFromSuperview() 
     self.proxyView = nil 
    } 
} 

Dies funktioniert gut, außer dass ich die Statusleiste in der Eingabe Vollbild-Animation zu verbergen, und zeigen Sie es in der Abfahrt Vollbild-Animation Dadurch springt meine Draufsicht zurück, ohne zu animieren.

Hinweis: Die Variable isFullscreen verbirgt die Statusleiste.

override var prefersStatusBarHidden: Bool { 
    return isFullscreen 
} 

override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { 
    return .slide 
} 

Hier sind Gifs der Animationen:

Horizonal

Vertical

Beachten Sie die obere der beiden und der Boden der Landschaft ein (einfacher auf die Landschaft zu sehen). Oben wird der Spieler-Frame sofort auf die alte Position gesetzt, und das bewegt alles um 20px (oder wie hoch die Statusleiste ist)

Es hat etwas mit der versteckten Statusleiste zu tun. Hat jemand eine Lösung?

Antwort

0

Ich fand es heraus. Es ist eine Art Hacky und nicht vollständig getestet, aber hier ist die Lösung, die ich mir ausgedacht habe.

Zuerst eine Variable abrufen, um die Höhe der Statusleiste zu speichern (nicht 0).

var statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.height != 0 ? UIApplication.shared.statusBarFrame.height : 20.0 

Dann richten Sie Benachrichtigungen für eine Statusleiste Rahmen ändern.

NotificationCenter.default.addObserver(self, selector: #selector(SKPlayerViewController.updateLocalStatusBarFrameHeight), name: .UIApplicationDidChangeStatusBarFrame, object: nil) 

nun in dem Verfahren, aktualisieren Sie Ihre Variable nur dann, wenn die Höhe nicht 0 ist wir die Höhe sparen, weil die Statusleiste möglicherweise nicht 20 (wenn in Anruf, usw.) sein.

@objc private func updateLocalStatusBarFrameHeight() { 
     let height = UIApplication.shared.statusBarFrame.height 
     if height > 0 { 
      self.statusBarHeight = height 
     } 
    } 

Nun, ich meine aktualisiert exitFullScreenToEmbed() den berechneten Frames Ursprung durch die statusBarHeight nur, wenn nicht Landschaft zu subtrahieren (weil die Statusleiste in der Landschaft versteckt).

private func exitFullScreenToEmbed() { 

    var frame = self.view.window?.convert(self.view.frame, to: self.proxyView?.superview) 
    self.proxyView?.superview?.addSubview(self.view) 

    if !(UIApplication.shared.statusBarOrientation == .landscapeRight || UIApplication.shared.statusBarOrientation == .landscapeLeft) { 
     frame?.origin.y -= self.statusBarHeight 
    } 

    self.view.frame = frame! 

    self.isFullscreen = false 

    UIView.animate(withDuration: 0.25, animations: { 

     self.view.frame = self.proxyView!.frame 

     self.view.layoutIfNeeded() 
     self.setNeedsStatusBarAppearanceUpdate() 
    }) { (_) in 
     self.proxyView?.removeFromSuperview() 
     self.proxyView = nil 
    } 
} 

Wenn dies jemand geholfen hat, sind Sie willkommen. Ich bin nur hier, um etwas Wissen zu teilen :)