[英]SwiftUI: Allowing user to enable Picture-in-Picture with the press of a button (iOS)
I'm designing an app that allows the user to view a certain video in a SwiftUI view.我正在设计一个应用程序,允许用户在 SwiftUI 视图中查看某个视频。 I want to support PiP, and AVPictureInPictureController.isPictureInPictureSupported() always returns true, while pipController.isPictureInPicturePossible sometimes returns true, but not usually while the video is actually playing.
我想支持 PiP,并且 AVPictureInPictureController.isPictureInPictureSupported() 总是返回 true,而 pipController.isPictureInPicturePossible 有时会返回 true,但通常不会在视频实际播放时返回。 It's possible I misunderstand how to use AVPictureInPictureController.
我可能误解了如何使用 AVPictureInPictureController。
My app initializes a view, called a FullScreenVideoView, with the following code:我的应用程序使用以下代码初始化了一个名为 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
}
Then, inside the view body, it displays the video by calling the playerController defined in the initializer:然后,在视图主体中,它通过调用在初始化程序中定义的 playerController 来显示视频:
playerController
.frame(height: aspectRatio * geometry.size.width)
.onTapGesture {
if self.model.player.avPlayer.isPlaying {
self.model.pause()
} else {
self.model.play()
}
}
The playerController is a wrapper on an AVPlayerViewController: 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) {
}
} }
A button is supposed to start PiP:一个按钮应该启动 PiP:
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)
Any help would be much appreciated.任何帮助将非常感激。 I can't find any helpful information on starting PiP in SwiftUI.
我找不到任何有关在 SwiftUI 中启动 PiP 的有用信息。
Note- the correct background capability is enabled.注意 - 启用了正确的后台功能。 Also, in my AppDelegate didFinishLaunchingWithOptions method, I have this code that seems to be required for PiP:
此外,在我的 AppDelegate didFinishLaunchingWithOptions 方法中,我有这个 PiP 似乎需要的代码:
do {
try audioSession.setCategory(AVAudioSession.Category.playback)
} catch {
print("Audio session failed")
}
Your code actually mostly works - at least inside my SwiftUI-code I pretty much have the same steps as you described.您的代码实际上大部分都有效 - 至少在我的 SwiftUI 代码中,我的步骤与您描述的几乎相同。
However, I do a bit more on the playerLayer and maybe this causes the pipController to actually work.但是,我在 playerLayer 上做了更多,也许这会导致 pipController 实际工作。
Here is what I do with the playerLayer inside my View-definition, I add it as a separate controls layer:这是我在 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)!
}
}
I am not 100% sure if this extra sublayer is really causing the pipController to improve.我不是 100% 确定这个额外的子层是否真的导致 pipController 改进。
Also, I am not using KHKVideoPlayer
but rather plain AVPlayer(url: url)
.另外,我没有使用
KHKVideoPlayer
,而是使用普通的AVPlayer(url: url)
。
And I am not using AVPlayerViewController
at all since doing all in SwiftUI.而且我根本没有使用
AVPlayerViewController
,因为在 SwiftUI 中做了所有事情。
And of course, I also add the Background-mode to make pip possible...当然,我还添加了背景模式以使 pip 成为可能......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.