SwiftUI:允许用户通过按下按钮启用画中画(iOS)
Posted
技术标签:
【中文标题】SwiftUI:允许用户通过按下按钮启用画中画(iOS)【英文标题】:SwiftUI: Allowing user to enable Picture-in-Picture with the press of a button (iOS) 【发布时间】:2021-07-12 23:13:26 【问题描述】:我正在设计一个允许用户在 SwiftUI 视图中观看特定视频的应用。我想支持画中画,并且 AVPictureInPictureController.isPictureInPictureSupported() 总是返回 true,而 pipController.isPictureInPicturePossible 有时会返回 true,但通常不会在视频实际播放时返回。 我可能误解了如何使用 AVPictureInPictureController。
我的应用使用以下代码初始化了一个名为 FullScreenVideoView 的视图:
init(player: KHKVideoPlayer, aspectRatio: CGFloat, presentingViewController pvc: UIViewController?)
self.aspectRatio = aspectRatio
self.pvc = pvc
self.model = FullScreenVideoViewerModel(player: player)
self.playerController = KHKPlayerController(player: player.avPlayer, cornerRadius: 0)
if AVPictureInPictureController.isPictureInPictureSupported()
self.pipController = AVPictureInPictureController(playerLayer: AVPlayerLayer(player: player.avPlayer))!
self.isMuted = player.avPlayer.isMuted
然后,在视图主体中,它通过调用初始化器中定义的 playerController 来显示视频:
playerController
.frame(height: aspectRatio * geometry.size.width)
.onTapGesture
if self.model.player.avPlayer.isPlaying
self.model.pause()
else
self.model.play()
playerController 是 AVPlayerViewController 的包装器:
struct KHKPlayerController: UIViewControllerRepresentable
typealias UIViewControllerType = AVPlayerViewController
var player: AVPlayer
var cornerRadius: CGFloat?
init(player: AVPlayer)
self.player = player
init(player: AVPlayer, cornerRadius: CGFloat)
self.player = player
self.cornerRadius = cornerRadius
func makeUIViewController(context: Context) -> AVPlayerViewController
let playerVC = AVPlayerViewController()
playerVC.showsPlaybackControls = false
playerVC.player = player
playerVC.view.layer.masksToBounds = true
playerVC.view.layer.cornerRadius = cornerRadius ?? 8
return playerVC
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context)
一个按钮应该用来启动画中画:
RectangleButton(action:
print("pip is possible: \(pipController?.isPictureInPicturePossible ?? false)")
pipController?.startPictureInPicture()
, imageSystemName: "pip.enter", foregroundColor: UI.Constants.primaryColor, backgroundColor: UI.Constants.tertiaryColor, width: 35, height: 25, cornerRadius: 3)
任何帮助将不胜感激。我找不到任何有关在 SwiftUI 中启动 PiP 的有用信息。
注意 - 启用了正确的后台功能。另外,在我的 AppDelegate didFinishLaunchingWithOptions 方法中,我有这个 PiP 似乎需要的代码:
do
try audiosession.setCategory(AVAudioSession.Category.playback)
catch
print("Audio session failed")
【问题讨论】:
【参考方案1】:您的代码实际上大部分都有效 - 至少在我的 SwiftUI 代码中,我的步骤与您描述的几乎相同。
但是,我在 playerLayer 上做的更多,也许这会导致 pipController 实际工作。
这是我在 View-definition 中对 playerLayer 所做的操作,我将其添加为单独的控件层:
player = AVPlayer(url: url)
playerLayer = AVPlayerLayer()
playerLayer.player = player
layer.addSublayer(playerLayer)
playerLayer.videoGravity = .resizeAspect
playerLayer.frame = self.bounds
if let playerLayer = playerLayer
if AVPictureInPictureController.isPictureInPictureSupported()
pipController = AVPictureInPictureController(playerLayer: playerLayer)!
我不能 100% 确定这个额外的子层是否真的导致 pipController 改进。
另外,我没有使用KHKVideoPlayer
,而是使用普通的AVPlayer(url: url)
。
而且我根本没有使用AVPlayerViewController
,因为在 SwiftUI 中完成了所有工作。
当然,我还添加了背景模式以使 pip 成为可能...
【讨论】:
以上是关于SwiftUI:允许用户通过按下按钮启用画中画(iOS)的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:当我按下按钮时如何打开(App-)电话设置?