0

我尝试在AVPlayerViewControllertvOS 电影应用程序中添加一个跳过介绍按钮(如 Netflix)。我将它作为子视图添加到 中contentOverlayView,当我让它出现时,我强制使用preferredFocusEnvironments. 一切都很好......直到用户导航到其他地方(例如搜索栏或视频资产信息视图)。然后按钮失去焦点(预期),并且永远不能通过用户交互再次获得焦点。我尝试过了:

  • 添加一个UIFocusGuide()
  • 把我的按钮直接放在AVPlayerViewController's view
  • 添加一个自己的子视图,其中包含到视图的AVPlayerViewController按钮
  • 添加一个自己的子视图,其中包含按钮contentOverlayView
  • 在同一子视图上的我的按钮旁边、下方、上方添加其他几个按钮(对于上述每种情况)

最后一种方法表明,其他按钮都无法通过用户交互获得焦点,因此看起来,出于同样的原因,用户无法关注 skip-intro-button。但这是什么原因呢?添加自定义交互元素的正确做法是什么AVPlayerViewController?有人有什么想法吗?

4

1 回答 1

0

尝试回答我的主要问题“向 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()
    }
}

我希望这对你们中的一些人有所帮助,他们来到这里却找不到其他答案。

于 2021-04-28T16:03:17.600 回答