You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中AVPlayer上层UIButton点击事件无法触发的问题求助

解决AVPlayerLayer上层UIButton点击事件不触发的问题

这个问题我之前也碰到过,核心原因是你混淆了UIView响应链和CALayer图层层级的区别,导致触摸事件根本传不到你的按钮上。

问题根源分析

你代码里把btn.layer添加到了playerLayer这个CALayer中,但UIButton作为UIView,并没有被添加到任何UIView的层级里——只有它的图层在图层树中,而iOS的触摸事件是通过UIView的响应链来传递的,CALayer本身并不参与触摸事件的处理。所以点击时系统找不到这个按钮,自然触发不了点击事件;而直接调用sendActions(for:)是绕过了触摸事件传递流程,直接调用目标方法,所以能正常响应。

两种修复方案

方案1:直接将UIButton添加到视图层级(适合当前用AVPlayerLayer的场景)

把你代码里的playerLayer.addSublayer(btn.layer)替换成将按钮作为子视图添加到当前控制器的view中,同时确保按钮在播放器图层的上方:

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib.
    guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else { return }
    // Create an AVPlayer, passing it the HTTP Live Streaming URL.
    let player = AVPlayer(url: url)
    // Create a new AVPlayerViewController and pass it a reference to the player.
    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = self.view.bounds
    
    let btn = UIButton(type: .roundedRect)
    btn.backgroundColor = UIColor.yellow
    btn.setTitle("Do stuff 1", for: .normal)
    btn.frame = CGRect(x: 0, y: 330, width: 300, height: 300)
    btn.addTarget(
        self,
        action: #selector(self.pressButton(button:)),
        for: .touchUpInside)
    
    // 关键修改:将按钮添加到视图层级,而非仅仅添加图层
    self.view.addSubview(btn)
    // 确保按钮在播放器图层上方(可选,默认视图层级会在图层之上,但保险起见可以加上)
    self.view.bringSubviewToFront(btn)
    
    self.view.layer.addSublayer(playerLayer)
    player.play()
}

方案2:使用AVPlayerViewController的contentOverlayView(官方推荐方式)

如果你可以改用AVPlayerViewController来管理播放器,官方专门提供了contentOverlayView属性,用于添加自定义叠加UI,它会自动处理层级和交互问题:

override func viewDidLoad() { 
    super.viewDidLoad() 
    guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else { return }
    
    let player = AVPlayer(url: url)
    let playerVC = AVPlayerViewController()
    playerVC.player = player
    playerVC.view.frame = self.view.bounds
    
    // 将AVPlayerViewController添加为子控制器
    self.addChild(playerVC)
    self.view.addSubview(playerVC.view)
    playerVC.didMove(toParent: self)
    
    let btn = UIButton(type: .roundedRect)
    btn.backgroundColor = .yellow
    btn.setTitle("Do stuff 1", for: .normal)
    btn.frame = CGRect(x: 0, y: 330, width: 300, height: 300)
    btn.addTarget(self, action: #selector(pressButton(button:)), for: .touchUpInside)
    
    // 使用官方提供的叠加视图添加按钮,无需担心交互问题
    playerVC.contentOverlayView?.addSubview(btn)
    
    player.play()
}

额外注意点

  • 不需要手动设置btn.isUserInteractionEnabled = true,UIButton默认就是开启用户交互的。
  • 如果使用方案1,若发现按钮还是被播放器遮挡,可以调整btn.layer.zPosition的值,设置为比playerLayer.zPosition大的数值,确保按钮图层在最上方。

内容的提问来源于stack exchange,提问作者phoenix2010

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:31:00