尝试回答我的主要问题“向 AVPlayerViewController 添加自定义交互元素的正确做法是什么?” 我:
自从我在 1.5 年前发布这个问题以来,我并没有对跳过介绍功能的实现进行太多更改。因此,每当用户使用遥控器时,按钮都会失去焦点,我唯一改变的是,每当发生这种情况时,我都会隐藏按钮,通过实现didUpdateFocus(in:with:)
类似于这样:
if let previouslyFocusedView = context.previouslyFocusedView {
if previouslyFocusedView == skipIntroButton {
changeSkipIntroButtonVisibility(to: 0.0)//animates alpha value
}
}
(我不完全确定,为什么我不将它设置为isHidden = true
)
然而,与此同时,我不得不为我们的播放器实现更复杂的覆盖,即“开始下一个视频/观看积分”的东西,带有预告片、一些按钮、倒计时/进度条等等。对于上述问题,很明显,我无法采用这种contentOverlayView
方法。所以我决定以“传统方式”来实现它,通过UIViewController
在玩家的视图之上呈现一个完整的视图,如下所示:
func showNextVideoOverlay() {
guard let nextVideoTeaser = nextVideoTeaser else { return }
let nextVideoOverlay = NextVideoAnnouncementViewController(withTeaser: nextVideoTeaser, player: player)
nextVideoOverlay.nextVideoAnnouncementDelegate = self
nextVideoOverlay.modalPresentationStyle = .overFullScreen
present(nextVideoOverlay, animated: true, completion: nil)
}
当然,它NextVideoAnnouncementViewController
是透明的,因此仍然可以观看视频。我发现这种直截了当的方法效果很好,我真的不知道,为什么我在实施跳过介绍时没有考虑过。
我的 QA 同事发现了一件棘手的事情,你应该知道(我认为,我记得,这对于不同的设备和不同的遥控器以及不同的 tvOS 版本是不同的——试试吧):
覆盖的视图控制器阻止来自遥控器的大部分命令,您可以分别在视图控制器内导航而不影响播放器 - 除了播放/暂停按钮。那会暂停播放器,但不可能从那里恢复。这是因为播放(av)播放器总是听这个按钮,而暂停的播放器不会。所以我还必须实现这样的东西:
func addRemoteButtonRecognizer() {
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(playPauseButtonPressed))
tapRecognizer.allowedPressTypes = [NSNumber(value: UIPress.PressType.playPause.rawValue)]
self.view.addGestureRecognizer(tapRecognizer)
}
@objc func playPauseButtonPressed(sender: AnyObject) {
nextVideoAnnouncementDelegate?.remotePlayButtonPressed()
}
func remotePlayButtonPressed() {
if player?.playerStatus == .paused {
player?.play()
} else {
player?.pause()
}
}
我希望这对你们中的一些人有所帮助,他们来到这里却找不到其他答案。