无法触摸包含 AVPlayerLayer 的 UIView

Posted

技术标签:

【中文标题】无法触摸包含 AVPlayerLayer 的 UIView【英文标题】:Cannot touch the UIView containing AVPlayerLayer 【发布时间】:2019-05-17 06:53:14 【问题描述】:

我在 UIImageView 中添加了一个图层 AVPlayerLayer,并在 UIImageView 中添加了 UITapGestureRecognizer。是的,我已经给了委托,并且 UIImageView 也启用了用户交互。但水龙头不工作。

有没有人详细了解AVPlayerLayer。

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")

【问题讨论】:

添加你目前尝试过的代码。 我尝试使用图像视图。它正在工作 【参考方案1】:

检查您是否添加了AVPlayerLayer。在index O 添加图层,而不是将其添加到顶部。

使用insertSublayer(_:at:) 而不是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")
    

现在,只要您点击viewtapHandler(_:) 方法就会被调用。

不要忘记手动启用userInteractionimageView

self.imageView.isUserInteractionEnabled = true

【讨论】:

是的,我已将其添加到顶部仅表示索引为 0。仍然无法正常工作 然后添加代码,以便我可以调试您面临的问题。 设置 imageViewTap.delegate = self 并将您的 viewController 设置为 UIGestureRecognizerDelegate 另外,看看userInteractionimageView 是否没有被禁用。 另外,在UI Inspector 中,检查是否有其他view 位于imageView 的顶部。【参考方案2】:

使用以下自定义视频播放器代码。

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
    

【讨论】:

是的,我使用过捏合手势和平移手势,效果很好。

以上是关于无法触摸包含 AVPlayerLayer 的 UIView的主要内容,如果未能解决你的问题,请参考以下文章

似乎无法获得 AVPlayerLayer 的视频高度

如何检测 UI 图像上的触摸?

在移动设备上使用可排序的触摸事件 + jquery-ui 无法按预期工作

可拖动的 jquery ui 触摸防止专注于 Chrome 上的输入

MPVolumeView Airplay 仅在镜像时触摸

向上传递 AVPlayerLayer 引用