![](/img/trans.png)
[英]How to detect fullscreen mode using AVPlayerViewController in Swift?
[英]How to make a AVPlayerViewController go to fullscreen programmatically?
我正在尝试以编程方式将AVPlayerViewController go 从“嵌入式”模式变为全屏模式,但是对于已发布的 API 这似乎是不可能的。
有没有我缺少的解决方法? 我有兴趣获得与用户按下控件右下角的全屏按钮时获得的相同的 animation。
使用 MPMoviePlayerController 不是一个可行的选择,因为我可能一次播放多个视频。
谢谢。
AVPlayerViewController 是 UIViewController 的子类,因此它可以像任何其他视图控制器子类一样呈现。 你能使用presentViewController:animated:completion
吗?
self.avPlayerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:self.avPlayerController animated:YES completion:nil];
然后在左上角显示“完成”按钮。
针对 iOS 11 更新
没有支持以编程方式使用 AVPlayerViewController 全屏显示的方法(我认为有点疏忽)。
但是, AVPlayerViewController 确实包含一个私有方法,可以做到这一点。 鉴于您不应该调用私有方法,您必须自己决定是否要使用它。
AVPlayerViewController+Fullscreen.h
#import <AVKit/AVKit.h>
@interface AVPlayerViewController (Fullscreen)
-(void)goFullscreen;
@end
AVPlayerViewController+Fullscreen.m
#import "AVPlayerViewController+Fullscreen.h"
@implementation AVPlayerViewController (Fullscreen)
-(void)goFullscreen {
NSString *selectorForFullscreen = @"transitionToFullScreenViewControllerAnimated:completionHandler:";
if (@available(iOS 11.3, *)) {
selectorForFullscreen = @"transitionToFullScreenAnimated:interactive:completionHandler:";
} else if (@available(iOS 11.0, *)) {
selectorForFullscreen = @"transitionToFullScreenAnimated:completionHandler:";
}
SEL fsSelector = NSSelectorFromString([@"_" stringByAppendingString:selectorForFullscreen]);
if ([self respondsToSelector:fsSelector]) {
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:fsSelector]];
[inv setSelector:fsSelector];
[inv setTarget:self];
NSInteger index = 2; //arguments 0 and 1 are self and _cmd respectively, automatically set
BOOL animated = YES;
[inv setArgument:&(animated) atIndex:index];
index++;
if (@available(iOS 11.3, *)) {
BOOL interactive = YES;
[inv setArgument:&(interactive) atIndex:index]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
index++;
}
id completionBlock = nil;
[inv setArgument:&(completionBlock) atIndex:index];
[inv invoke];
}
}
@end
在 iOS11 中, AVPlayerViewController
有 2 个新属性: entersFullScreenWhenPlaybackBegins
和exitsFullScreenWhenPlaybackEnds
。 您可以在播放开始后立即启用全屏模式,并在播放结束时禁用这些属性。 如果您需要在延迟一段时间后启用全屏模式,您可以使用ToddH在他的回答中提到的私有 API 方法。 但是在 iOS11 中_transitionToFullScreenViewControllerAnimated:completionHandler:
方法不再可用,有相同的方法称为_transitionToFullScreenAnimated:completionHandler:
。 第二种方法接受与第一种方法相同的参数。
我可以展示一个如何使用它的例子。 首先,您需要在UIViewController
创建AVPlayerViewController
实例:
private let playerController : AVPlayerViewController = {
if let urlForPlayer = URL(string: "your_video_url") {
$0.player = AVPlayer(url: urlForPlayer)
}
return $0
} (AVPlayerViewController())
然后您需要为 AVPlayerViewController 设置视图并将其添加到您当前的控制器视图中。 函数setupAVplayerController
可以为你做到:
private func setupAVplayerController() {
self.addChildViewController(self.playerController)
self.playerController.view.frame = CGRect(x: 0.0, y: 0.0, width: 200.0, height: 200.0)
self.view.addSubview(self.playerController.view)
self.playerController.didMove(toParentViewController: self)
}
函数enterFullscreen
强制AVPlayerViewController
全屏模式:
private func enterFullscreen(playerViewController:AVPlayerViewController) {
let selectorName : String = {
if #available(iOS 11, *) {
return "_transitionToFullScreenAnimated:completionHandler:"
} else {
return "_transitionToFullScreenViewControllerAnimated:completionHandler:"
}
}()
let selectorToForceFullScreenMode = NSSelectorFromString(selectorName)
if playerViewController.responds(to: selectorToForceFullScreenMode) {
playerViewController.perform(selectorToForceFullScreenMode, with: true, with: nil)
}
}
现在您需要在需要的地方调用所有这些函数,例如在viewDidAppear
:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//Your code
self.setupAVplayerController()
self.playerController.player?.play()
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
self.enterFullscreen(playerViewController:self.playerController)
}
}
不要忘记,这个基于私有 API 调用的解决方案是不推荐使用的。
更新:ToddH 答案的 Swift 4 版本:
private func enterFullscreen(playerViewController: AVPlayerViewController) {
let selectorName: String = {
if #available(iOS 11.3, *) {
return "_transitionToFullScreenAnimated:interactive:completionHandler:"
} else if #available(iOS 11, *) {
return "_transitionToFullScreenAnimated:completionHandler:"
} else {
return "_transitionToFullScreenViewControllerAnimated:completionHandler:"
}
}()
let selectorToForceFullScreenMode = NSSelectorFromString(selectorName)
if playerViewController.responds(to: selectorToForceFullScreenMode) {
playerViewController.perform(selectorToForceFullScreenMode, with: true, with: nil)
}
}
作为 ToddH 答案的 iOS 14 小更新:要调用的私有 API是enterFullScreenAnimated:completionHandler:
。 所以这里有一个关于 AVPlayerViewController 的扩展进入全屏。
extension AVPlayerViewController {
func enterFullScreen(animated: Bool) {
perform(NSSelectorFromString("enterFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
func exitFullScreen(animated: Bool) {
perform(NSSelectorFromString("exitFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
}
此实现不提供完成回调。 如果您将 Swift 闭包传递给completionHandler
参数,它会在底层 Obj-C API 中崩溃。 我还没有研究如何通过闭包使其工作。
ToddH 的 Swift 3 版本:
extension AVPlayerViewController {
func goFullScreen() {
let selector = NSSelectorFromString("_transitionToFullScreenViewControllerAnimated:completionHandler:")
if self.responds(to: selector) {
// first argument is animated (true for me), second is completion handler (nil in my case)
self.perform(selector, with: true, with: nil)
}
}
}
你可以只设置 AVPlayerViewController 的videoGravity属性。
if(fullscreen)
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
else
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspect];
}
我不需要使用任何受限代码。
为此,我假设您已将AVPlayerViewController
添加为子视图控制器。
然后为此,您首先必须删除子视图控制器,然后将其再次显示为全屏控制器,并将AVPlayer
视图正确附加到其父视图。
这是我如何做到的。 请注意,我正在使用一个名为Easy Peasy
的库来恢复playerVC.view
约束 - 也可以通过适当的约束来做到这一点。
@objc func fullscreenButtonClicked() {
playerVC.willMove(toParentViewController: nil)
playerVC.view.removeFromSuperview()
playerVC.removeFromParentViewController()
self.present(self.playerVC, animated: false, completion: {
self.playerVC.view.easy.layout(Top(), Right(), Left(), Bottom())
})
}
对于“嵌入式” AVPlayerViewController
实例,很容易以编程方式让它在全屏模式下开始播放,而无需破解任何内容(调用私有方法)。 您只需将其entersFullScreenWhenPlaybackBegins
属性设置为 true。
您需要将控制器作为子 VC 添加到主 VC,基本上就是这样。 在viewDidAppear(_:)
您需要在控制器的player
属性上调用play()
方法 - 播放将自动以全屏方式开始。
对于这些棘手的 API,通常最好检查 Apple 示例代码; 我认为这可能对很多 AVPlayer 用例有用: 在 iOS 中使用 AVKit 。
非常简单,只需设置playerViewController.videoGravity =.resizeAspectFill
它全屏显示:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.