veeresh kumbar
veeresh kumbar

Reputation: 805

Cannot touch the UIView containing AVPlayerLayer

I have added a layer AVPlayerLayer to the UIImageView and added the UITapGestureRecognizer to the UIImageView. And yes I have given the delegate and user interaction is also enabled for UIImageView. But the tap is not working.

Does anyone know about AVPlayerLayer in detail.

let imageViewTap = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
imageViewTap.numberOfTapsRequired = 1
imageView.addGestureRecognizer(imageViewTap)

let item = AVPlayerItem(asset: videoAsset)
videoPlayer = AVPlayer(playerItem: item)
videoPlayerLayer = AVPlayerLayer(player: videoPlayer)
videoPlayerLayer.frame = imageView.bounds
videoPlayerLayer.backgroundColor = UIColor.black.cgColor
imageView.layer.insertSublayer(videoPlayerLayer, at: 0)

 @objc func imageViewTapped(){
        print("my code here")
}

Upvotes: 1

Views: 494

Answers (2)

PGDev
PGDev

Reputation: 24341

Check were have you added the AVPlayerLayer. Add layer at index O instead of adding it to the top.

Use insertSublayer(_:at:) instead of addSublayer(_:)

class ViewController: UIViewController, UIGestureRecognizerDelegate {
    @IBOutlet weak var imageView: UIImageView!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.imageView.isUserInteractionEnabled = true
        self.addPlayer()
    }

    func addPlayer() {
        if let url = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") {
            let player = AVPlayer(url: url)
            let playerLayer = AVPlayerLayer(player: player)
            playerLayer.frame = self.imageView.bounds
            playerLayer.videoGravity = .resizeAspect
            self.imageView.layer.insertSublayer(playerLayer, at: 0)
            player.play()
        }

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:)))
        tapGesture.delegate = self
        self.imageView.addGestureRecognizer(tapGesture)
    }

    @objc func tapHandler(_ sender: UIGestureRecognizerDelegate) {
        print("view tapped")
    }
}

Now, whenever you tap on the view, tapHandler(_:) method will be called.

Don't forget to enable userInteraction of imageView manually.

self.imageView.isUserInteractionEnabled = true

Upvotes: 1

Bhavik Modi
Bhavik Modi

Reputation: 1565

Use following code of custom video player.

protocol UIGestureDeleagte: class {
    func singleTappedRecognize(_ singleTapGesture: UITapGestureRecognizer)
}

class CustomVideoPlayerView: UIView, UIGestureRecognizerDelegate {

    weak var delegate: UIGestureDeleagte?
    var videoPlayer: AVPlayer!
    var playerLayer: AVPlayerLayer?

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialSetup()

    }

    override func encode(with aCoder: NSCoder) {
        super.encode(with: aCoder)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        playerLayer?.frame = self.bounds
    }

    deinit {
        playerLayer = nil
        videoPlayer = nil
        for recognizer in self.gestureRecognizers ?? [] {
            self.removeGestureRecognizer(recognizer)
        }
        NotificationCenter.default.removeObserver(self)
    }

    private func initialSetup() {
        self.isUserInteractionEnabled = true
        self.isMultipleTouchEnabled = false

        videoPlayer = AVPlayer()

        let playerLayerFrame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
        if (playerLayer == nil) {
            playerLayer = AVPlayerLayer()
            playerLayer?.name = "AVPlayerLayer"
            playerLayer?.frame = playerLayerFrame
            playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
            self.layer.addSublayer(playerLayer!)
        }
    }

    private func setupGestures() {
        for recognizer in self.gestureRecognizers ?? [] {
            self.removeGestureRecognizer(recognizer)
        }

        let tapGesture = UITapGestureRecognizer(target: self, action:#selector(handleTapGesture(_:)))
        tapGesture.delegate = self
        self.addGestureRecognizer(tapGesture)
    }

    func setupVideoPlayer(videoURL: URL) {
        let playerItem = AVPlayerItem(asset: AVAsset(url: videoURL))
        videoPlayer.replaceCurrentItem(with: playerItem)
        playerLayer?.player = videoPlayer
    }

    @objc func handleTapGesture(_ tapGesture: UITapGestureRecognizer) {
        delegate?.singleTappedRecognize(tapGesture)
    }

    func playVideo() {
        videoPlayer?.play()
    }

    func pauseVideo() {
        videoPlayer?.pause()
    }

    func stopVideo() {
        videoPlayer?.pause()
        videoPlayer?.seek(to: CMTime.zero)
    }

    //MARK:- UIGestureRecognizerDelegate Methods
    private func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

Upvotes: 0

Related Questions