当将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")!)
}
它如何正常工作:
如何中断:
答案 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.
}
}