【问题标题】:AVPlayerViewController full screen rotation behavior in portrait only app仅纵向应用程序中的 AVPlayerViewController 全屏旋转行为
【发布时间】:2018-06-21 21:44:22
【问题描述】:

在仅纵向 iOS 应用中嵌入 AVPlayerViewController 时,如果在设备保持横向时全屏播放视频,则当播放器退出全屏时,应用似乎会卡在奇怪的布局中。

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

以下是使用 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

【问题讨论】:

  • 您找到解决方案了吗?
  • @RafaelaLourenço 实际上不,这似乎是一个平台错误,或者您不应该嵌入 AVPlayerViewController (这对我来说没有意义,因为它上面有一个全屏按钮)。我认为 Nabil 的答案是可行的,但它绝对是一个 hack。
  • 感谢您的回答.. 这似乎真的是一个错误。我希望苹果尽快修复。
  • 不管怎样,iOS12 似乎已经解决了这个问题。

标签: ios iphone swift xcode


【解决方案1】:

当您离开播放器全屏时,您将进入视图控制器的 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
}

【讨论】:

  • 这完全解决了问题,并且不会导致任何奇怪的 UI 卡顿。感谢您找到这个问题并提供您的知识,Ivan!
  • 对我来说,viewWillAppear 在离开AVPlayerViewController 的全屏时没有被调用。
  • 根据我的测试,在 iOS 10 上它没有进入 viewWillApper,但它进入了 iOS 11。
  • 如果应用只支持纵向模式,这并不能解决问题。如果只支持纵向模式,下一个问题是应用现在处于横向模式
  • 你应该自己处理这个问题,这个修复不会导致你的问题。
【解决方案2】:

您可以识别播放器何时变为全屏并为您的视图控制器强制显示纵向或横向。

这不是最好的解决方案,但至少可以避免损坏的 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
    }

【讨论】:

    【解决方案3】:

    我尝试使用 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.
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多