![](/img/trans.png)
[英]How to detect fullscreen mode using AVPlayerViewController in Swift?
[英]How to make a AVPlayerViewController go to fullscreen programmatically?
我正在嘗試以編程方式將AVPlayerViewController go 從“嵌入式”模式變為全屏模式,但是對於已發布的 API 這似乎是不可能的。
有沒有我缺少的解決方法? 我有興趣獲得與用戶按下控件右下角的全屏按鈕時獲得的相同的 animation。
使用 MPMoviePlayerController 不是一個可行的選擇,因為我可能一次播放多個視頻。
謝謝。
AVPlayerViewController 是 UIViewController 的子類,因此它可以像任何其他視圖控制器子類一樣呈現。 你能使用presentViewController:animated:completion
嗎?
self.avPlayerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:self.avPlayerController animated:YES completion:nil];
然后在左上角顯示“完成”按鈕。
針對 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
在 iOS11 中, AVPlayerViewController
有 2 個新屬性: entersFullScreenWhenPlaybackBegins
和exitsFullScreenWhenPlaybackEnds
。 您可以在播放開始后立即啟用全屏模式,並在播放結束時禁用這些屬性。 如果您需要在延遲一段時間后啟用全屏模式,您可以使用ToddH在他的回答中提到的私有 API 方法。 但是在 iOS11 中_transitionToFullScreenViewControllerAnimated:completionHandler:
方法不再可用,有相同的方法稱為_transitionToFullScreenAnimated:completionHandler:
。 第二種方法接受與第一種方法相同的參數。
我可以展示一個如何使用它的例子。 首先,您需要在UIViewController
創建AVPlayerViewController
實例:
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 調用的解決方案是不推薦使用的。
更新:ToddH 答案的 Swift 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)
}
}
作為 ToddH 答案的 iOS 14 小更新:要調用的私有 API是enterFullScreenAnimated:completionHandler:
。 所以這里有一個關於 AVPlayerViewController 的擴展進入全屏。
extension AVPlayerViewController {
func enterFullScreen(animated: Bool) {
perform(NSSelectorFromString("enterFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
func exitFullScreen(animated: Bool) {
perform(NSSelectorFromString("exitFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
}
此實現不提供完成回調。 如果您將 Swift 閉包傳遞給completionHandler
參數,它會在底層 Obj-C API 中崩潰。 我還沒有研究如何通過閉包使其工作。
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)
}
}
}
你可以只設置 AVPlayerViewController 的videoGravity屬性。
if(fullscreen)
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
else
{
[self.avPlayerController
setVideoGravity:AVLayerVideoGravityResizeAspect];
}
我不需要使用任何受限代碼。
為此,我假設您已將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())
})
}
對於“嵌入式” AVPlayerViewController
實例,很容易以編程方式讓它在全屏模式下開始播放,而無需破解任何內容(調用私有方法)。 您只需將其entersFullScreenWhenPlaybackBegins
屬性設置為 true。
您需要將控制器作為子 VC 添加到主 VC,基本上就是這樣。 在viewDidAppear(_:)
您需要在控制器的player
屬性上調用play()
方法 - 播放將自動以全屏方式開始。
對於這些棘手的 API,通常最好檢查 Apple 示例代碼; 我認為這可能對很多 AVPlayer 用例有用: 在 iOS 中使用 AVKit 。
非常簡單,只需設置playerViewController.videoGravity =.resizeAspectFill
它全屏顯示:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.