Martin
Martin

Reputation: 1143

How to detect the toggle on the display of playback controls with AVPlayerViewController?

I'd like to know if it is possible to detect when the playback controls appear or disappear from the AVPlayerViewController view. I'm trying to add a UI element on my player that must follow the playback controls display. Appearing only when the controls are displayed, disappearing otherwise

I don't seem to find any value that I can observe on AVPlayerViewController to achieve this nor any callbacks or delegate methods.

My project is in Swift.

Upvotes: 12

Views: 1931

Answers (1)

Simon McLoughlin
Simon McLoughlin

Reputation: 8475

Managed to find something that works (for iOS at least) based off a comment on another post. Might be flaky, might not work for all platforms.

Create an AVPlayerViewController subclass and setup an observer on one of its subviews, checking for changes to the hidden property. Tried to do it in a way that avoids explicitly using anything marked private to avoid any app store issues. Code below for anyone else looking for the same, and please let me know if you find anything better

import AVKit

protocol CustomAVPlayerViewControllerDelegate: AnyObject {
    
    func playbackControlsChanged(visible: Bool)
}

class CustomAVPlayerViewController: AVPlayerViewController {
    
    private var viewToMonitor: UIView? = nil
    private var previousValue = true
    
    public weak var customDelegate: CustomAVPlayerViewControllerDelegate? = nil
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let container = view.subviews.first
        viewToMonitor = container?.subviews.last
        previousValue = viewToMonitor?.isHidden ?? true
        
        viewToMonitor?.addObserver(self, forKeyPath: "hidden", context: nil)
    }
    
    deinit {
        viewToMonitor?.removeObserver(self, forKeyPath: "hidden")
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        // Check if its the correct element and avoid double trigger
        if keyPath == "hidden", let v = viewToMonitor, previousValue != v.isHidden {
            previousValue = v.isHidden
            customDelegate?.playbackControlsChanged(visible: !v.isHidden)
        }
    }
}

Upvotes: 2

Related Questions