隐藏AVPlayerViewController中的控件 – 仅在开始时
如果将AVPlayerViewController.showsPlaybackControls设置为false,则控件将不会显示。 即使你点击屏幕。
我想控制开始隐藏,但仍然能够通过点击召唤他们。 如果我将提到的属性设置为true,则它们开始可见。 (是的,他们几秒钟后褪色。)有没有办法开始隐藏,但仍然可以访问?
更新:我最终使自己的控制更好的自定义。 这是更困难的,但值得的时间。 请阅读Apple的示例代码以供参考。 这是关于实现画中画,但也关于制作自定义控件: https : //developer.apple.com/library/prerelease/ios/samplecode/AVFoundationPiPPlayer/Introduction/Intro.html
更新:点击时,AVPlayerViewController只触发touchesBegan事件,而不是touchesEnded事件。 但足以显示控件。
首先你需要隐藏控制。 把这个代码放在AVPlayerViewController之前
YourAVPlayerViewController.showsPlaybackControls = false
然后子类AVPlayerViewController并添加此function:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { self.showsPlaybackControls = true super.touchesBegan(touches, withEvent: event) }
旧的SOLLUTION:
我刚刚解决了这个问题。 主要的想法是在AVPlayerViewController的顶部放置一个UIView,以实现点击手势,并在不再需要时隐藏该UIView。
代码如下:
import AVKit import UIKit // Create a custom AVPlayerViewController @available(iOS 8.0, *) final class CustomAVPlayerViewController: AVPlayerViewController { // Create a UIView to put on top of all lazy var topView = UIView(frame: CGRectMake(0, 0, width, height)) override func viewDidLoad() { super.viewDidLoad() // For sure, set it to clearcolor // (DON'T set alpha = 0 because it will stop receiving user interaction) topView.backgroundColor = UIColor.clearColor() // Add it to the view of AVPlayerViewController self.view.addSubview(topView) // Bring it to front self.view.bringSubviewToFront(topView) // Add a tap gesture recognizer topView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap")) } // Handle the tap func handleTap() { // Show the control self.showsPlaybackControls = true // Hide the topView. You can unhide it when needed later. self.topView.hidden = true } }
而当你需要隐藏控制,做到这一点:
var AVViewController = CustomAVPlayerViewController() ... // Hide controls AVViewController.showsPlaybackControls = false // Show topView AVViewController.topView.hidden = false
我想我已经解决了这个使用dynamic手势识别器的关系。 该解决scheme避免了自定义控件(为了一致性),只使用公共API,并没有将AVPlayerViewController
(如其他答案中指出的那样明确地不允许)进行子类化。
就是这样:
-
制作一个embedded
AVPlayerViewController
的容器视图控制器。 (不pipe控件如何,这都很有用,因为你需要把播放逻辑放在某个地方。) -
最初将
showsPlaybackControls
设置为false
。 -
添加一个UITapGestureRecognizer来识别初始的水龙头。
-
在手势识别器的操作方法中,将
showsPlaybackControls
设置为true
。 -
到目前为止,它会工作,但控制将立即消失在最初的水龙头。 为了解决这个问题,请将自己设置为手势识别器的委托,实现
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:
并返回true
以用于任何其他单击手势识别器。
这里是Swift的实际实现。 检查andreyvit / ModalMoviePlayerViewController回购最新的代码:
import UIKit import AVKit import AVFoundation public class ModalMoviePlayerViewController: UIViewController { private let fileName: String private let loop: Bool private var item: AVPlayerItem! private var player: AVPlayer! internal private(set) var playerVC: AVPlayerViewController! private var waitingToAutostart = true public init(fileName: String, loop: Bool = true) { self.fileName = fileName self.loop = loop super.init(nibName: nil, bundle: nil) } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func viewDidLoad() { super.viewDidLoad() let url = NSBundle.mainBundle().URLForResource(fileName, withExtension: nil)! item = AVPlayerItem(URL: url) player = AVPlayer(playerItem: item) player.actionAtItemEnd = .None player.addObserver(self, forKeyPath: "status", options: [], context: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ModalMoviePlayerViewController.didPlayToEndTime), name: AVPlayerItemDidPlayToEndTimeNotification, object: item) playerVC = AVPlayerViewController() playerVC.player = player playerVC.videoGravity = AVLayerVideoGravityResizeAspectFill playerVC.showsPlaybackControls = false let playerView = playerVC.view addChildViewController(playerVC) view.addSubview(playerView) playerView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] playerView.frame = view.bounds playerVC.didMoveToParentViewController(self) let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ModalMoviePlayerViewController.handleTap)) tapGesture.delegate = self view.addGestureRecognizer(tapGesture) } deinit { player.pause() player.removeObserver(self, forKeyPath: "status") NSNotificationCenter.defaultCenter().removeObserver(self) } func togglePlayPause() { if isPlaying { pause() } else { play() } } func restart() { seekToStart() play() } func play() { if player.status == .ReadyToPlay { player.play() } else { waitingToAutostart = true } } func pause() { player.pause() waitingToAutostart = false } var isPlaying: Bool { return (player.rate > 1 - 1e-6) || waitingToAutostart } private func performStateTransitions() { if waitingToAutostart && player.status == .ReadyToPlay { player.play() } } public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { performStateTransitions() } @objc func didPlayToEndTime() { if isPlaying && loop { seekToStart() } } private func seekToStart() { player.seekToTime(CMTimeMake(0, 10)) } public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { if !playerVC.showsPlaybackControls { playerVC.showsPlaybackControls = true } super.touchesBegan(touches, withEvent: event) } } extension ModalMoviePlayerViewController: UIGestureRecognizerDelegate { @IBAction func handleTap(sender: UIGestureRecognizer) { if !playerVC.showsPlaybackControls { playerVC.showsPlaybackControls = true } } /// Prevents delivery of touch gestures to AVPlayerViewController's gesture recognizer, /// which would cause controls to hide immediately after being shown. /// /// `-[AVPlayerViewController _handleSingleTapGesture] goes like this: /// /// if self._showsPlaybackControlsView() { /// _hidePlaybackControlsViewIfPossibleUntilFurtherUserInteraction() /// } else { /// _showPlaybackControlsViewIfNeededAndHideIfPossibleAfterDelayIfPlaying() /// } public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { if !playerVC.showsPlaybackControls { // print("\nshouldBeRequiredToFailByGestureRecognizer? \(otherGestureRecognizer)") if let tapGesture = otherGestureRecognizer as? UITapGestureRecognizer { if tapGesture.numberOfTouchesRequired == 1 { return true } } } return false } }
聚会的答案是好的。 我会重写touchesCancelled,而不是控制不显示,然后再次隐藏。
override public func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) { super.touchesCancelled(touches, withEvent: event) // toggle the player controls on if they were set to off if !self.showsPlaybackControls { self.showsPlaybackControls = true } }
在Swift 3中做一个简单的方法是设置myController.showsPlaybackControls = false
,并用button或手势识别器覆盖整个玩家视图。 我将其embedded故事板上另一个控制器中的另一个视图,以使其变得简单,并且不覆盖播放器控制器。 诀窍就是在点击一次之后隐藏button,因为玩家控制器此后会跟踪点击来显示/隐藏控件。
@IBAction func enableControls(button:UIButton) { controller?.showsPlaybackControls = true button.isHidden = true //The button is only needed once, then the player takes over. }