在AVPlayerViewController中完成按钮单击事件

问题描述 投票:11回答:7

我想在AVPlayerViewController中播放本地视频,但没有找到完成按钮的点击事件。

我的视频可以在AVPlayerViewController中播放,但我没有找到下一个按钮,上一个按钮和完成按钮点击事件。

ios objective-c avplayer avplayerviewcontroller
7个回答
15
投票

正式没有Done Button点击事件,Apple的工程师说它here

至于我的研究,我发现如果单击Done Button,有一种但实际上是间接的方式来获取事件。

我发现AVPlayerViewController的唯一变量是点击完成按钮时更改的是AVPlayerViewController.view.frame。首先,view.frame出现在viewController的中心。

如果你用animated : true呈现它,它会转到viewController的底部,然后回到中心。单击完成后,它会返回到底部。

如果你用animated : false呈现它只会有2个变化:当你开始播放视频时,frame将位于viewController的中心,而当单击Done时,frame将位于底部。

因此,如果你在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
}

另外,我发现当你单击完成时,AVPlayerViewController没有被解雇,你可以在ParentViewController.presentedViewController中看到它,所以你不能将观察者添加到这个属性


13
投票

我这样做是为了从Done获取AVPlayerViewController按钮点击事件。 首先,像波纹管一样创建Notification.Name的扩展

extension Notification.Name {
static let kAVPlayerViewControllerDismissingNotification = Notification.Name.init("dismissing")
}

现在,创建AVPlayerViewController的扩展并覆盖viewWillDisappear,如bellow

// 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
投票

这是@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
    } 
} 

0
投票

我有同样的问题,我发现了另一个技巧(与YoutubePlayer swift框架一起工作,在webview中播放视频,但你可能能够适应其他用途)。

在我的情况下,按下Done按钮并按下全屏视频​​播放器上的Pause按钮都会在YoutubePlayer上产生pause事件。但是,当视频在不同的窗口中播放时,我将应用程序的主窗口子类化,并覆盖了becomeKeyresignKey函数来存储我的窗口是否是关键窗口,如下所示:

class MyWindow:UIWindow {
    override func becomeKey() {
        Services.appData.myWindowIsKey = true
    }

    override func resignKey() {
        Services.appData.myWindowIsKey = false
    }
}

一旦我有了,我可以在视频状态暂停时检查我的窗口是否是键 - 当按下Done按钮时,我的窗口是关键窗口,我可以关闭我的视频视图控制器,在Pause情况下我的窗口不是关键窗口,所以我什么都不做。


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()
    }
 }

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")
}

-5
投票

你可以看看这个Stackoverflow post,这里是一个github's project供参考。你将不得不使用这个:

 self.showsPlaybackControls = true

还请看看Apple's documentation

© www.soinside.com 2019 - 2024. All rights reserved.