iOS开发:强制AVPlayerViewController全屏横屏启动问题
解决AVPlayerViewController启动即强制全屏横屏的问题
我明白你的痛点——明明AVPlayerViewController能正常播放视频,翻转设备也能切换全屏,但就是没法让它一启动就直接进入横屏全屏状态。结合你Tab Bar+Navigation Controller的架构,给你几个关键步骤来搞定这个问题:
1. 先确保App和父视图控制器支持横屏
首先,你的App得允许横屏方向:
- 打开
Info.plist,添加UISupportedInterfaceOrientations数组,包含UIInterfaceOrientationPortrait、UIInterfaceOrientationLandscapeLeft、UIInterfaceOrientationLandscapeRight这三个值(如果不需要倒转就不用加UpsideDown)。
然后,在present AVPlayerViewController的那个ViewController里,重写屏幕旋转相关的属性,让它支持横屏:
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { // 支持除了倒转以外的所有方向,或者直接写.landscape覆盖竖屏 return .allButUpsideDown } override var shouldAutorotate: Bool { return true }
如果你的ViewController是嵌套在Navigation Controller里的,别忘了自定义一个导航控制器,让它继承子控制器的旋转设置:
class CustomNavController: UINavigationController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return topViewController?.supportedInterfaceOrientations ?? .portrait } override var shouldAutorotate: Bool { return topViewController?.shouldAutorotate ?? true } }
之后把Tab Bar里的导航控制器替换成这个自定义的。
2. 强制旋转屏幕+启动时进入全屏
接下来是核心操作:在present AVPlayerViewController之前,先强制把设备方向转到横屏,然后让播放器直接进入全屏模式。这里要适配iOS 16前后的API差异:
// 1. 先准备好你的AVPlayer实例 let videoURL = URL(string: "你的视频流地址")! let player = AVPlayer(url: videoURL) let playerVC = AVPlayerViewController() playerVC.player = player // 2. 禁止画中画,避免干扰全屏逻辑 playerVC.allowsPictureInPicturePlayback = false // 设置视频填充模式为全屏填充 playerVC.videoGravity = .resizeAspectFill // 必须设置为全屏present模式 playerVC.modalPresentationStyle = .fullScreen // 3. 强制旋转屏幕(适配iOS 16+) if #available(iOS 16.0, *) { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene { windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeLeft)) { error in if let error = error { print("旋转失败:\(error.localizedDescription)") } } } } else { // iOS 15及以下的旧方法 UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") } // 4. present播放器,并在完成后强制进入全屏 present(playerVC, animated: true) { // 确保播放器已经准备好后再触发全屏 if playerVC.player?.currentItem?.status == .readyToPlay { playerVC.enterFullscreen(animated: true) } else { // 如果还没准备好,监听状态变化后再全屏 playerVC.player?.currentItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil) } }
如果用了KVO监听状态,记得在deinit里移除观察者:
deinit { playerVC.player?.currentItem?.removeObserver(self, forKeyPath: "status") } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "status" { if let item = object as? AVPlayerItem, item.status == .readyToPlay { playerVC.enterFullscreen(animated: true) item.removeObserver(self, forKeyPath: "status") } } }
3. 额外注意点
- 不要在
viewDidLoad里直接执行这段代码,最好放在用户触发的事件里(比如按钮点击),因为App启动初期屏幕旋转可能会有冲突。 - 如果你的Tab Bar Controller限制了旋转,也要确保它支持横屏,或者在present播放器时临时放开限制。
这样操作后,AVPlayerViewController就能一启动就直接进入横屏全屏状态了,和翻转设备后的效果一致。
内容的提问来源于stack exchange,提问作者Curious101
相关产品推荐
相关产品推荐

