ios 如何以编程方式让 AVPlayerViewController 进入全屏模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30817667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:24:28  来源:igfitidea点击:

How to make a AVPlayerViewController go to fullscreen programmatically?

iosobjective-cswiftios8

提问by ikaver

I'm trying to make a AVPlayerViewControllergo to full screen mode programmatically, coming from "embedded" mode, however this does not appear to be possible with the published API.

我试图让AVPlayerViewController以编程方式进入全屏模式,来自“嵌入式”模式,但是这似乎不可能与已发布的 API 实现。

Is there a workaround that I'm missing? I'm interested in obtaining the same animation to the one that you get when the user presses the full screen button on the bottom right of the controls.

有没有我缺少的解决方法?我有兴趣获得与用户按下控件右下角的全屏按钮时获得的动画相同的动画。

Using MPMoviePlayerController is not a viable alternative since I might have more than one video playing at a time.

使用 MPMoviePlayerController 不是一个可行的选择,因为我可能一次播放多个视频。

Thanks.

谢谢。

回答by Daniel J

AVPlayerViewController is a subclass of UIViewController, so it is presentable like any other view controller subclass. Are you able to use presentViewController:animated:completion?

AVPlayerViewController 是 UIViewController 的子类,因此它像任何其他视图控制器子类一样可呈现。你能用presentViewController:animated:completion吗?

self.avPlayerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:self.avPlayerController animated:YES completion:nil];

This then shows the "Done" button in the top left-hand corner.

然后在左上角显示“完成”按钮。

回答by ToddH

Updated for iOS 11

针对 iOS 11 更新

There is no supported way to programmatically go fullscreen with AVPlayerViewController (a bit of an oversight in my opinion).

没有支持以编程方式使用 AVPlayerViewController 全屏显示的方法(我认为有点疏忽)。

However, AVPlayerViewController does contain a private methodthat does exactly that. You'll have to decide for yourself whether you'd want to use it or not given you're not supposed to call private methods.

但是,AVPlayerViewController 确实包含一个私有方法,可以做到这一点。鉴于您不应该调用私有方法,您必须自己决定是否要使用它。

AVPlayerViewController+Fullscreen.h

AVPlayerViewController+Fullscreen.h

#import <AVKit/AVKit.h>

@interface AVPlayerViewController (Fullscreen)

-(void)goFullscreen;

@end

AVPlayerViewController+Fullscreen.m

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

回答by Roman Podymov

In iOS11 there are 2 new properties for AVPlayerViewController: entersFullScreenWhenPlaybackBeginsand exitsFullScreenWhenPlaybackEnds. You can enable full screen mode right after playback begins and disable it when playback ends with these properties. If you need to enable fullscreen mode after some delay you can use private API methods as ToddHmentioned in his answer. However in iOS11 _transitionToFullScreenViewControllerAnimated:completionHandler:method is not available anymore, there is the same method called _transitionToFullScreenAnimated:completionHandler:. The second method accepts the same arguments as the first one.

在 iOS11 中,AVPlayerViewController:entersFullScreenWhenPlaybackBeginsexitsFullScreenWhenPlaybackEnds. 您可以在播放开始后立即启用全屏模式,并在播放结束时禁用这些属性。如果您需要在延迟一段时间后启用全屏模式,您可以使用ToddH他的回答中提到的私有 API 方法。但是在 iOS11_transitionToFullScreenViewControllerAnimated:completionHandler:方法中不再可用,有相同的方法称为_transitionToFullScreenAnimated:completionHandler:. 第二种方法接受与第一种方法相同的参数。

I can show an example how to use it. First of all you need to create AVPlayerViewControllerinstance in your UIViewController:

我可以展示一个如何使用它的例子。首先,您需要AVPlayerViewController在您的UIViewController

private let playerController : AVPlayerViewController = {

    if let urlForPlayer = URL(string: "your_video_url") {

        
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)
}
.player = AVPlayer(url: urlForPlayer) } return
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)
    }
}
} (AVPlayerViewController())

Then you need to setup view for AVPlayerViewController and add it to your current controller view. Function setupAVplayerControllercan do it for you:

然后您需要为 AVPlayerViewController 设置视图并将其添加到您当前的控制器视图中。函数setupAVplayerController可以为您做到:

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)
    }
}

Function enterFullscreenforces full screen mode for AVPlayerViewController:

功能enterFullscreen强制全屏模式AVPlayerViewController

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)
    }
}

And now you need to call all these functions where you need it, for example in viewDidAppear:

现在您需要在需要的地方调用所有这些函数,例如viewDidAppear

if(fullscreen)
{
    [self.avPlayerController 
     setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
else
{
    [self.avPlayerController 
    setVideoGravity:AVLayerVideoGravityResizeAspect];
}

Don't forget that this solution based on private API calls that is not recommended to use.

不要忘记,这个基于私有 API 调用的解决方案是不推荐使用的。

回答by Ivan Georgiev

UPDATE: Swift 4 version of ToddH's answer:

更新:ToddH 答案的 Swift 4 版本:

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)
        }
    }
}

回答by The iCoder

You can just set the videoGravityproperty of AVPlayerViewController.

你可以只设置AVPlayerViewController的videoGravity属性。

    @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())
        })
    }

回答by Milan Nosá?

Swift 3 version for the answer of ToddH:

ToddH 的 Swift 3 版本:

##代码##

回答by rahulg

I did not have the need to use any restricted code.

我不需要使用任何受限代码。

For this, I am assuming that you have added the AVPlayerViewControlleras a child view controller.

为此,我假设您已经添加了AVPlayerViewController作为子视图控制器。

Then for that you will first have to remove the child view controller and then present it again as a fullscreen controller as well attach the AVPlayerview properly to it's parent view.

然后为此,您首先必须删除子视图控制器,然后将其再次显示为全屏控制器,并将AVPlayer视图正确附加到其父视图。

Here is how I did it. Please note that I am using a library called Easy Peasyfor restoring the playerVC.viewconstraints - one can do that with proper constraints as well.

这是我如何做到的。请注意,我正在使用一个Easy Peasy用于恢复playerVC.view约束的库- 也可以通过适当的约束来做到这一点。

##代码##

回答by Ivan

For an 'embedded' AVPlayerViewControllerinstance, it is quite easy to programmatically have it start playback in full screen mode, and without hacking anything (calling private methods). You just need to set its entersFullScreenWhenPlaybackBeginsproperty to true.

对于“嵌入式”AVPlayerViewController实例,很容易以编程方式让它在全屏模式下开始播放,而无需修改任何内容(调用私有方法)。您只需要将其entersFullScreenWhenPlaybackBegins属性设置为 true。

You need to add the controller as a child VC to the main VC, and that's basically it. In viewDidAppear(_:)you need to call play()method on the controller's playerproperty - playback will be automatically started in fullscreen.

您需要将控制器作为子 VC 添加到主 VC,基本上就是这样。在viewDidAppear(_:)您需要调用play()控制器player属性上的方法时- 播放将自动以全屏方式开始。

It's often best to check Apple sample code for these kind of tricky APIs; I think this one might be useful for a lot of AVPlayer use cases: Using AVKit in iOS.

对于这些棘手的 API,通常最好检查 Apple 示例代码;我认为这可能对很多 AVPlayer 用例有用:在 iOS 中使用 AVKit