仅肖像应用中的AVPlayerViewController全屏旋转行为

时间:2018-06-21 21:44:23

标签: ios iphone swift xcode

当将AVPlayerViewController嵌入到仅纵向模式的iOS应用程序中时,如果在设备保持横向放置的状态下全屏显示视频,则当播放器退出全屏显示时,该应用程序可能会卡在怪异的布局中。

这是错误还是我做错了什么?

以下是使用Xcode 9.4.1,swift 4,iOS 11.4,模拟器或物理设备在干净项目中进行重现的方法。

ViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    //Create the player and add as child view controller
    let playerVC = AVPlayerViewController()
    self.addChildViewController(playerVC)

    //Place player's view in self
    playerVC.view.frame = CGRect(x: 10, y: 40, width: 355, height: 200)
    self.view.addSubview(playerVC.view)

    //Load example video
    playerVC.player = AVPlayer(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")!)
}

它如何正常工作:

  • 播放视频,全屏播放
  • 旋转到风景,视频旋转
  • 关闭全屏,无论屏幕或设备方向如何,应用都会恢复为纵向
  • 例如:https://imgur.com/a/MPFmzyH

如何中断:

  • 播放视频,将设备旋转到横向(屏幕不旋转)
  • 全屏显示
  • 退出全屏
  • 屏幕中断,旋转无法解决
  • 例如:https://imgur.com/a/hDdmu20

3 个答案:

答案 0 :(得分:4)

当播放器保持全屏显示时,您将进入View Controller的viewWillApper。因此,在viewWillAppear中,尝试将窗口框架设置为等于屏幕边界。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
    appDelegate.window?.rootViewController?.view.frame = UIScreen.main.bounds
}

答案 1 :(得分:0)

您可以确定播放器何时进入全屏状态,并为视图控制器强制设置肖像或风景。

这不是最佳解决方案,但至少避免了UI损坏:

    import AVFoundation
    import AVKit

    var isPlayerFullscreen: Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        //Create the player and add as child view controller
        let playerVC = AVPlayerViewController()
        self.addChildViewController(playerVC)

        //Place player's view in self
        playerVC.view.frame = CGRect(x: 10, y: 40, width: 355, height: 200)
        self.view.addSubview(playerVC.view)

        //Load example video
        playerVC.player = AVPlayer(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")!)

        //Add an observer for playerVC object
        playerVC.addObserver(self, forKeyPath: "videoBounds", options: NSKeyValueObservingOptions.new, context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
    {
        if keyPath == "videoBounds", let rect = change?[.newKey] as? NSValue
        {
            let playerRect: CGRect = rect.cgRectValue
            if playerRect.size.height <= 200 {
                print("Video not in full screen")                
                UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
isPlayerFullscreen = false
            } else {
                print("Video in full screen")
                isPlayerFullscreen = true
            }
        }
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return isPlayerFullscreen ? UIInterfaceOrientationMask.landscape: UIInterfaceOrientationMask.portrait
    }

    override var shouldAutorotate: Bool {
        return true
    }

答案 2 :(得分:0)

我试图使用willTransitionToTraitCollection方法来实现。 我有一个viewController,它具有AVPlayerViewController和AVPlayer和内联playerView的引用 1.将方向锁定为allButUpsideDown 2.加载时,将AVPlayerViewController作为子级加载并将其捕捉到PlayerView 3.并覆盖willTransitionToNewTraitCollection方法


override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    super.willTransition(to: newCollection, with: coordinator)
    coordinator.animate(alongsideTransition: { [unowned self] _ in

      if newCollection.verticalSizeClass == .compact {

        self.videoPlayerController.willMove(toParent: nil)
        self.videoPlayerController.view.removeFromSuperview()
        self.videoPlayerController.removeFromParent()

        DispatchQueue.main.async {
          self.present(self.videoPlayerController,
                       animated: false) {
                        // Do some stuff if needed
          }
        }
      }
      else if newCollection.verticalSizeClass == .regular {
        self.dismiss(animated: false) {
          DispatchQueue.main.async {

            self.videoPlayerController.view.frame = self.playerView.bounds
            self.playerView.addSubview(self.videoPlayerController.view)
          }
        }
      }
    }) { _ in
        // Lock the orientation to allButUpSideDown after animation.
    }
  }