背景
PiPとはPicture in Pictureの略で、動画をスマホの画面にオーバーレイして表示するアレのことです。
YouTubeとかでよくありますよね。
あれをSwiftUIで実装しようとすると、ググった結果がよくわからないのでまとめてみました。
コード
やるべきポイントは三つです。そのどれが欠けてもPiPは動作しません。
AppDelegate
import AVFAudio
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)
return true
}
}
@main
struct mainApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}AppDelegateでこの設定を入れます。
VideoPlayerView
動画のURLが取得済みで、それを再生したい場合には以下のようなコードが利用できます。
URLはローカルでもリモートでも大丈夫です。
import AVKit
import SwiftUI
import Foundation
struct VideoPlayerView: UIViewControllerRepresentable {
let streamURL: URL
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller: AVPlayerViewController = .init()
let player: AVPlayer = .init(url: streamURL)
controller.player = player
controller.canStartPictureInPictureAutomaticallyFromInline = true
controller.player?.play()
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
}Capabilities
Targets > App > Signing & Capabilities > Background Modes > Audio, AirPlay and Picture in Piture
にチェックを入れます。
Implementing Picture-in-Picture in Swift for iOSの最初の方をそのまま実践するだけです。
まとめ
あとはVideoPlayerViewを適当なタイミングで呼び出します。
引数にstreamURLを持っているので、
struct TestView: View {
@State private var streamURL: URL?
var body: some View {
EmptyView()
.sheet(item: streamURL, content: { streamURL in
VideoPlayerView(streamURL: streamURL)
.ignoresSafeArea(.all)
})
}
}みたいな感じで実装すればよいです。
記事は以上。