web-dev-qa-db-ja.com

AVPlayerViewControllerをプログラムでフルスクリーンにする方法は?

私は AVPlayerViewController を「埋め込み」モードからプログラムでフルスクリーンモードにしようとしていますが、これは公開されたAPIでは不可能なようです。

私が見逃している回避策はありますか?ユーザーがコントロールの右下にある全画面ボタンを押したときに表示されるアニメーションと同じアニメーションを取得することに興味があります。

MPMoviePlayerControllerの使用は、一度に複数のビデオを再生する可能性があるため、実行可能な代替手段ではありません。

ありがとう。

20
ikaver

AVPlayerViewControllerはUIViewControllerのサブクラスであるため、他のView Controllerサブクラスと同様に表示可能です。 presentViewController:animated:completionを使用できますか?

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

これにより、左上隅に「完了」ボタンが表示されます。

14
Daniel J

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

IOS11には、AVPlayerViewControllerの2つの新しいプロパティがあります:entersFullScreenWhenPlaybackBeginsexitsFullScreenWhenPlaybackEnds。これらのプロパティを使用して、再生開始直後に全画面モードを有効にし、再生が終了したときに無効にすることができます。しばらくしてフルスクリーンモードを有効にする必要がある場合は、 ToddHhis answer で言及されているように、プライベートAPIメソッドを使用できます。ただし、iOS11では_transitionToFullScreenViewControllerAnimated:completionHandler:メソッドは使用できなくなりました。_transitionToFullScreenAnimated:completionHandler:という同じメソッドがあります。 2番目のメソッドは、最初のメソッドと同じ引数を受け入れます。

使い方の例を示すことができます。まず、AVPlayerViewControllerUIViewControllerインスタンスを作成する必要があります。

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呼び出しに基づいていることを忘れないでください。

7
Roman Podymov

更新:Swift ToddHの答えの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)
    }
}
3
Ivan Georgiev

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

AVPlayerViewControllerのvideoGravityプロパティを設定するだけです。

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

制限されたコードを使用する必要はありませんでした。

このため、AVPlayerViewControllerを子View Controllerとして追加したと想定しています。

そのためには、まず子View Controllerを削除してから、それを再びフルスクリーンコントローラとして提示し、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())
        })
    }

0
rahulg