Last active
August 8, 2023 07:27
-
-
Save sharukmsd/e2fcf8f35a1ed9f57a0e2d742846262d to your computer and use it in GitHub Desktop.
SwiftUI video player with loading indicator
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 AVFoundation | |
import AVKit | |
import SwiftUI | |
struct VideoPlayer: UIViewRepresentable { | |
var videoURL: URL | |
let videoPlayerView = ActivityIndicatorPlayer() | |
func makeUIView(context: Context) -> ActivityIndicatorPlayer { | |
let player = AVPlayer(url: videoURL) | |
videoPlayerView.setPlayer(player: player) | |
videoPlayerView.startLoading() | |
player.addObserver(context.coordinator, forKeyPath: "status", options: [.old, .new], context: nil) | |
return videoPlayerView | |
} | |
func updateUIView(_ uiView: ActivityIndicatorPlayer, context: Context) {} | |
func makeCoordinator() -> Coordinator { | |
Coordinator(self) | |
} | |
class Coordinator: NSObject { | |
var parent: VideoPlayer | |
init(_ parent: VideoPlayer) { | |
self.parent = parent | |
} | |
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | |
if keyPath == "status", let change = change, let newValue = change[NSKeyValueChangeKey.newKey] as? Int { | |
if newValue == AVPlayer.Status.readyToPlay.rawValue { | |
parent.videoPlayerView.stopLoading() | |
} | |
} | |
} | |
} | |
} | |
class ActivityIndicatorPlayer: UIView { | |
private let playerViewController = AVPlayerViewController() | |
private let activityIndicator = UIActivityIndicatorView(style: .large) | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
configurePlayerView() | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
configurePlayerView() | |
} | |
private func configurePlayerView() { | |
addSubview(playerViewController.view) | |
addSubview(activityIndicator) | |
playerViewController.view.translatesAutoresizingMaskIntoConstraints = false | |
activityIndicator.translatesAutoresizingMaskIntoConstraints = false | |
NSLayoutConstraint.activate([ | |
playerViewController.view.topAnchor.constraint(equalTo: topAnchor), | |
playerViewController.view.leadingAnchor.constraint(equalTo: leadingAnchor), | |
playerViewController.view.trailingAnchor.constraint(equalTo: trailingAnchor), | |
playerViewController.view.bottomAnchor.constraint(equalTo: bottomAnchor), | |
activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor), | |
activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor) | |
]) | |
} | |
func setPlayer(player: AVPlayer?) { | |
playerViewController.player = player | |
} | |
func startLoading() { | |
activityIndicator.startAnimating() | |
} | |
func stopLoading() { | |
activityIndicator.stopAnimating() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment