Как сделать AVPlayerViewController доступным в полноэкранном режиме?
Я пытаюсь сделать AVPlayerViewController программным путем перейти в полноэкранный режим, исходя из "встроенного" режима, однако это не представляется возможным с опубликованным API.
Есть ли обходной путь, который мне не хватает? Я заинтересован в том, чтобы получить ту же анимацию, которую вы получаете, когда пользователь нажимает кнопку полного экрана в правом нижнем углу элементов управления.
Использование MPMoviePlayerController не является жизнеспособной альтернативой, поскольку у меня может быть одновременно несколько видеороликов.
Благодарю.
Ответы
Ответ 1
AVPlayerViewController является подклассом UIViewController, поэтому он представлен как любой другой подкласс диспетчера представлений. presentViewController:animated:completion
ли вы использовать presentViewController:animated:completion
?
self.avPlayerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:self.avPlayerController animated:YES completion:nil];
Затем отображается кнопка "Готово" в верхнем левом углу.
Ответ 2
Обновлено для 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
Ответ 3
В iOS11 есть два новых свойства для AVPlayerViewController
: entersFullScreenWhenPlaybackBegins
и exitsFullScreenWhenPlaybackEnds
. Вы можете включить полноэкранный режим сразу после начала воспроизведения и отключить его, когда воспроизведение заканчивается этими свойствами. Если вам нужно включить полноэкранный режим после некоторой задержки, вы можете использовать частные методы API, о которых упоминал Тоддх в своем ответе. Однако в iOS11 _transitionToFullScreenViewControllerAnimated:completionHandler:
метод больше не доступен, существует тот же метод, что и _transitionToFullScreenAnimated:completionHandler:
Второй метод принимает те же аргументы, что и первый.
Я могу показать пример, как его использовать. Прежде всего вам нужно создать экземпляр AVPlayerViewController
в вашем UIViewController
:
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, которые не рекомендуется использовать.
Ответ 4
ОБНОВЛЕНИЕ: Swift 4 версия ответа 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)
}
}
Ответ 5
Версия Swift 3 для ответа 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)
}
}
}
Ответ 6
Вы можете просто установить свойство videoGravity для AVPlayerViewController.
if(fullscreen)
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
else
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspect];
}
Ответ 7
У меня не было необходимости использовать какой-либо ограниченный код.
Для этого я предполагаю, что вы добавили 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())
})
}