web-dev-qa-db-fra.com

Comment faire en sorte qu'un AVPlayerViewController passe en plein écran par programme?

J'essaie de créer AVPlayerViewController passe en mode plein écran par programmation, en passant du mode "incorporé", mais cela ne semble pas possible avec l'API publiée. 

Y at-il une solution de contournement qui me manque? Je souhaite obtenir la même animation que celle obtenue lorsque l'utilisateur appuie sur le bouton plein écran en bas à droite des commandes.

L'utilisation de MPMoviePlayerController n'est pas une solution viable, car plusieurs vidéos pourraient être lues à la fois.

Merci.

19
ikaver

AVPlayerViewController est une sous-classe de UIViewController, il est donc présentable comme toute autre sous-classe de contrôleur de vue. Pouvez-vous utiliser presentViewController:animated:completion

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

Ceci affiche ensuite le bouton "Terminé" dans le coin supérieur gauche.

14
Daniel J

Mis à jour pour iOS 11

Il n’existe pas de moyen de passer en mode plein écran par programmation avec AVPlayerViewController (ce qui est un oubli dans mon opinion). 

Cependant, AVPlayerViewController contient une méthode privée qui fait exactement cela. Vous devrez décider vous-même si vous souhaitez l'utiliser ou non, étant donné que vous n'êtes pas censé appeler des méthodes privées.

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
12
ToddH

Dans iOS11, il y a 2 nouvelles propriétés pour AVPlayerViewController: entersFullScreenWhenPlaybackBegins et exitsFullScreenWhenPlaybackEnds. Vous pouvez activer le mode plein écran dès le début de la lecture et le désactiver lorsque la lecture se termine avec ces propriétés. Si vous devez activer le mode plein écran après un certain délai, vous pouvez utiliser les méthodes de l'API privée telles que ToddH mentionné dans sa réponse . Cependant, dans iOS11, la méthode _transitionToFullScreenViewControllerAnimated:completionHandler: n'est plus disponible, il existe la même méthode appelée _transitionToFullScreenAnimated:completionHandler:. La seconde méthode accepte les mêmes arguments que la première. 

Je peux montrer un exemple d'utilisation. Tout d’abord, vous devez créer une instance AVPlayerViewController dans votre UIViewController:

private let playerController : AVPlayerViewController = {

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

        $0.player = AVPlayer(url: urlForPlayer)
    }
    return $0
} (AVPlayerViewController())

Ensuite, vous devez configurer la vue pour AVPlayerViewController et l'ajouter à la vue de votre contrôleur actuel. La fonction setupAVplayerController peut le faire pour vous:

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

La fonction enterFullscreen force le mode plein écran pour 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)
    }
}

Et maintenant, vous devez appeler toutes ces fonctions là où vous en avez besoin, par exemple dans 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)
    }
}

N'oubliez pas que cette solution basée sur des appels d'API privés qu'il n'est pas recommandé d'utiliser.

6
Roman Podymov

UPDATE: Swift 4 version de la réponse de ToddH:

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)
    }
}
2
Ivan Georgiev

Version Swift 3 pour la réponse de ToddH:

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)
        }
    }
}
2
Milan Nosáľ

Vous pouvez simplement définir la propriété videoGravity de AVPlayerViewController.

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