Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove buffering activity indicator from AVPlayerViewController

I'm implementing an iOS video player using AVPlayerViewController with custom playback controls (i.e., the showsPlaybackControls property is defined as NO). This seems to work properly in most cases, the only issue I'm seeing is that I would like to use a custom activity indicator with the player as well, but it seems that AVPlayerViewController shows a default activity indicator while buffering the video at some points.

Is there a way to remove this default activity indicator view from AVPlayerViewController?

The image shows what I'm describing, the controls at the bottom are custom and overlaid on top of the player, but the activity indicator is not.

player with custom controls and default activity indicator

like image 578
gutenbergn Avatar asked Mar 31 '16 18:03

gutenbergn


2 Answers

I made an extension of AVPlayerViewController that exposes the internal activity indicator. Here you go, with all the Swift 3 sexiness:

import AVKit

extension AVPlayerViewController {
    /// Activity indicator contained nested inside the controller's view.
    var activityIndicator: UIActivityIndicatorView? {
        // Indicator is extracted by traversing the subviews of the controller's `view` property.
        // `AVPlayerViewController`'s view contains a private `AVLoadingIndicatorView` that
        // holds an instance of `UIActivityIndicatorView` as a subview.
        let nestedSubviews: [UIView] = view.subviews
            .flatMap { [$0] + $0.subviews }
            .flatMap { [$0] + $0.subviews }
            .flatMap { [$0] + $0.subviews }
        return nestedSubviews.filter { $0 is UIActivityIndicatorView }.first as? UIActivityIndicatorView
    }

    /// Indicating whether the built-in activity indicator is hidden or not.
    var isActivityIndicatorHidden: Bool {
        set {
            activityIndicator?.alpha = newValue ? 0 : 1
        }
        get {
            return activityIndicator?.alpha == 0
        }
    }
}

With this, you can either easily style the UIActivityIndicatorView or just hide it all together, e.g.:

playerViewController.isActivityIndicatorHidden = true
like image 116
Gasper Avatar answered Nov 08 '22 21:11

Gasper


I also searched for this solution and the way I managed to make it is hide video player view controllers view once I started playing video and when video is ready to play I show it again.

private func playVideo() {

    videoPlayer?.play()

    self.addLoader()

    videoPlayerController.view.hidden = true

    videoPlayer?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: nil)
}

public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

    if (object?.isEqual(videoPlayer) == true && keyPath == "status") {

        self.removeLoader()
        videoPlayerController.view.hidden = false
    }
}
like image 27
Vladica Pešić Avatar answered Nov 08 '22 20:11

Vladica Pešić