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.
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.
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
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.
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)
}
}
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)
}
}
}
Vous pouvez simplement définir la propriété videoGravity de AVPlayerViewController.
if(fullscreen)
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
else
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspect];
}