Last active
November 24, 2023 18:59
-
-
Save satishVekariya/e0175c453623ad10e06195cc217e5447 to your computer and use it in GitHub Desktop.
AvPlayer wrapper for SwiftUI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import AVKit | |
public struct VideoPlayerView<Overlay: View>: View { | |
let overlay: Overlay | |
let player: AVPlayer | |
@State private var isShowOverlay = true | |
public init(_ player: AVPlayer, overlay: () -> (Overlay)) { | |
self.player = player | |
self.overlay = overlay() | |
} | |
public var body: some View { | |
AVPlayerViewRepresentable(player) { | |
// on touches began | |
isShowOverlay.toggle() | |
} | |
.ignoresSafeArea() | |
.overlay { | |
overlay | |
.onTapGesture { | |
isShowOverlay.toggle() | |
} | |
.opacity(isShowOverlay ? 1 : 0) | |
.animation(.default, value: isShowOverlay) | |
} | |
.task { | |
await hideOverlay() | |
} | |
.task(id: isShowOverlay) { | |
await hideOverlay() | |
} | |
.task(id: player.isPlaying) { | |
await hideOverlay() | |
} | |
} | |
private func hideOverlay() async { | |
guard isShowOverlay else { return } | |
try? await Task.sleep(for: .seconds(3)) | |
await MainActor.run { | |
if player.isPlaying { | |
isShowOverlay = false | |
} | |
} | |
} | |
} | |
public struct AVPlayerViewRepresentable: UIViewRepresentable { | |
let touchesBegan: (() -> ())? | |
let player: AVPlayer | |
public init(_ player: AVPlayer, touchesBegan: (() -> ())?) { | |
self.player = player | |
self.touchesBegan = touchesBegan | |
} | |
public func makeUIView(context: Context) -> AVPlayerLayerUIView { | |
let view = AVPlayerLayerUIView(touchesBegan: touchesBegan) | |
view.playerLayer.player = player | |
return view | |
} | |
public func updateUIView(_ uiView: AVPlayerLayerUIView, context: Context) { | |
uiView.playerLayer.player = player | |
} | |
} | |
public class AVPlayerLayerUIView: UIView { | |
let touchesBegan: (() -> ())? | |
public override class var layerClass: AnyClass { AVPlayerLayer.self } | |
public var playerLayer: AVPlayerLayer { layer as? AVPlayerLayer ?? .init(layer: layer) } | |
public init(touchesBegan: (() -> ())?) { | |
self.touchesBegan = touchesBegan | |
super.init(frame: .zero) | |
backgroundColor = .black | |
} | |
public required init?(coder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { | |
super.touchesBegan(touches, with: event) | |
touchesBegan?() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment