我想在AVPlayerViewController中播放本地视频,但未找到完成按钮的点击事件。
我的视频可以在AVPlayerViewController中播放,但我没有找到下一个按钮,上一个按钮和完成按钮点击事件。
答案 0 :(得分:15)
官方没有完成按钮点击事件,Apple的工程师说了here。
至于我的研究,我发现如果单击完成按钮,有一种但实际上是间接的方式来获取事件。
我发现AVPlayerViewController的唯一变量是AVPlayerViewController.view.frame
,它在点击完成按钮时会发生变化。
首先,view.frame出现在viewController的中心。
如果你用animated : true
呈现它,它会转到viewController的底部,然后回到中心。单击完成后,它将返回到底部。
如果您使用animated : false
呈现它,则只会有2个更改:当您开始播放视频时,框架将位于viewController的中心,而当单击完成时,框架将位于底部。
因此,如果您将观察者添加到AVPlayerViewController.view.frame
回调中的present(PlayerViewController, animated : true)
,您只会收到一个观察者的电话,当点击完成按钮并且视频视图将被取消时屏幕。
在我的情况下,AVPlayerViewController以动态方式呈现。以下代码对我有用:
Swift 3.0
override func viewDidLoad()
{
super.viewDidLoad()
let videoURL = NSURL(fileURLWithPath:Bundle.main.path(forResource: "MyVideo", ofType:"mp4")!)
let player = AVPlayer(url: videoURL as URL)
present(playerViewController, animated: false) { () -> Void in
player.play()
self.playerViewController.player = player
self.playerViewController.addObserver(self, forKeyPath: #keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
}}
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?)
{
print(self.playerViewController.view.frame)
//Player view is out of the screen and
//You can do your custom actions
}
另外,我发现当你点击Done时,AVPlayerViewController没有被解雇,你可以在ParentViewController.presentedViewController
看到它,所以你不能将观察者添加到这个属性
答案 1 :(得分:13)
我这样做是为了从Done
获取AVPlayerViewController
按钮点击事件。
首先,创建Notification.Name
的扩展名,如bellow
extension Notification.Name {
static let kAVPlayerViewControllerDismissingNotification = Notification.Name.init("dismissing")
}
现在,创建AVPlayerViewController
的扩展名并覆盖viewWillDisappear
,如下所述
// create an extension of AVPlayerViewController
extension AVPlayerViewController {
// override 'viewWillDisappear'
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// now, check that this ViewController is dismissing
if self.isBeingDismissed == false {
return
}
// and then , post a simple notification and observe & handle it, where & when you need to.....
NotificationCenter.default.post(name: .kAVPlayerViewControllerDismissingNotification, object: nil)
}
}
这仅仅是处理按钮事件的基本功能。
快乐的编码......
答案 2 :(得分:2)
目标c版本:(基于vmchar答案)
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL fileURLWithPath:path];
AVPlayer *player = [AVPlayer playerWithURL:url];
AVPlayerViewController *AVPlayerVc = [[AVPlayerViewController alloc] init];
if (AVPlayerVc) {
[self presentViewController:AVPlayerVc animated:YES completion:^{
[player play];
AVPlayerVc.player = player;
[AVPlayerVc addObserver:self forKeyPath:@"view.frame" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:nil];
}];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"view.frame"]) {
CGRect newValue = [change[NSKeyValueChangeNewKey]CGRectValue];
CGFloat y = newValue.origin.y;
if (y != 0) {
NSLog(@"Video Closed");
}
}
}
答案 3 :(得分:1)
这是@vmchar答案的一个小改进:
我们可以使用.isBeingDismissed方法来确保关闭AVPlayerViewController而不是分析帧。
...
let videoURL = NSURL(fileURLWithPath:"video.mp4")
let player = AVPlayer(url: videoURL as URL)
present(playerViewController!, animated: false) { () -> Void in
player.play()
self.playerViewController!.player = player
self.playerViewController!.addObserver(self, forKeyPath:#keyPath(UIViewController.view.frame), options: [.old, .new], context: nil)
...
然后观察值
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?)
{
if (playerViewController!.isBeingDismissed) {
// Video was dismissed -> apply logic here
}
}
答案 4 :(得分:1)
我找到了一种解决方法,而不必将AVPlayerViewController
子类化,文档明确指出您不应该这样做(https://developer.apple.com/documentation/avkit/avplayerviewcontroller)。它不是很漂亮,但是当AVPlayerViewController
被解雇时,通过给我一个地方运行代码来完成工作。
AnyViewController: UIViewController, AVPlayerViewControllerDelegate {
private let playerVC = AVPlayerViewController()
override func viewDidLoad() {
playerVC.delegate = self
}
func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
if playerViewController.isBeingDismissed {
playerViewController.dismiss(animated: false) { [weak self] in
self?.someDismissFunc()
}
}
}
}
据我所知:(
答案 5 :(得分:0)
我遇到了同样的问题,我发现了另一个技巧(适用于在webview中播放视频的YoutubePlayer swift框架,但您可以将其调整为其他用途)。
在我的情况下,按下Done
按钮并按全屏视频播放器上的Pause
按钮都会在YoutubePlayer上产生pause
事件。但是,当视频在不同的窗口中播放时,我将应用程序的主窗口子类化,并覆盖becomeKey
和resignKey
函数来存储我的窗口是否是关键窗口,如下:
class MyWindow:UIWindow {
override func becomeKey() {
Services.appData.myWindowIsKey = true
}
override func resignKey() {
Services.appData.myWindowIsKey = false
}
}
有了这个,我可以在视频状态暂停时查看我的窗口是否为按键 - 当按下Done
按钮时,我的窗口 是关键窗口我可以解雇我的视频视图控制器,在Pause
情况下,我的窗口不是关键窗口,所以我什么都不做。
答案 6 :(得分:0)
我想有很多方法可以给猫皮。我需要处理“完成”点击事件。就我而言,我想确保在单击“ X”并且完全关闭(关闭)AVPlayerViewController之后能够挂接到事件。
Swift 4.0
protocol TableViewCellVideoPlayerViewControllerDelegate: class {
func viewControllerDismissed()
}
class MyPlayerViewController: AVPlayerViewController {
weak var navDelegate: TableViewCellVideoPlayerViewControllerDelegate?
open override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isBeingDismissed {
self.navDelegate?.viewControllerDismissed()
}
}
}
class TodayCell: UITableViewCell, SFSafariViewControllerDelegate, TableViewCellVideoPlayerViewControllerDelegate {
func viewControllerDismissed() {
self.continueJourney()
}
}
答案 7 :(得分:0)
对我来说,最简单的解决方案是将AVPlayerViewController
子类化并为其添加简单的完成代码块。
class MYVideoController: AVPlayerViewController {
typealias DissmissBlock = () -> Void
var onDismiss: DissmissBlock?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isBeingDismissed {
onDismiss?()
}
}
}
用法
...
let avPlayerViewController = MYVideoController()
avPlayerViewController.onDismiss = { [weak self] in
print("dismiss")
}
答案 8 :(得分:-5)
您可以查看此Stackoverflow post,此处是github's project以供参考。你必须使用它:
self.showsPlaybackControls = true