SwiftUI中为AVPlayerViewController添加点击手势致控件失效的解决方法
解决SwiftUI中AVPlayerViewController手势冲突问题
问题原因
SwiftUI的.onTapGesture会在视图最上层添加手势识别器,直接拦截所有触摸事件,导致底层AVPlayerViewController的原生播放控件(比如播放/暂停按钮、进度条)无法响应触摸。
解决方案:在UIKit层级添加手势(推荐)
不在SwiftUI层面加手势,而是直接给AVPlayerViewController的视图添加UITapGestureRecognizer,并设置cancelsTouchesInView = false,这样既可以响应自定义点击,又不会阻止原生控件的触摸事件。
完整修改后的PlayerViewSUI代码
import SwiftUI import AVKit public struct PlayerViewSUI: UIViewControllerRepresentable { public let player: AVPlayer? public let showsPlaybackControls: Bool public var onTap: (() -> Void)? public init(player: AVPlayer?, showsPlaybackControls: Bool = true, onTap: (() -> Void)? = nil) { self.player = player self.showsPlaybackControls = showsPlaybackControls self.onTap = onTap } public func makeUIViewController(context: Context) -> AVPlayerViewController { let controller = AVPlayerViewController() controller.player = player controller.showsPlaybackControls = showsPlaybackControls controller.delegate = context.coordinator // 添加自定义点击手势 if let onTap = onTap { let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap)) // 关键设置:不阻止其他控件的触摸事件 tapGesture.cancelsTouchesInView = false controller.view.addGestureRecognizer(tapGesture) } return controller } public func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) { uiViewController.player = player uiViewController.showsPlaybackControls = showsPlaybackControls } public func makeCoordinator() -> Coordinator { Coordinator(parent: self) } public class Coordinator: NSObject, AVPlayerViewControllerDelegate { let parent: PlayerViewSUI init(parent: PlayerViewSUI) { self.parent = parent } @objc func handleTap() { parent.onTap?() } } }
使用方式
初始化PlayerViewSUI时直接传入点击回调,无需额外添加SwiftUI手势:
PlayerViewSUI(player: player, onTap: { print("Tapped") }) .frame(maxWidth: .infinity) .background(Color.black) .padding(.vertical, 20) .ignoresSafeArea() .navigationBarHidden(hideNavigationBar) .toolbarBackground(.visible, for: .navigationBar)
备选方案:SwiftUI simultaneousGesture(需注意层级)
如果坚持在SwiftUI层面添加手势,可以尝试.simultaneousGesture,但这种方法可能因视图层级问题失效,可靠性不如第一种方案:
PlayerViewSUI(player: player) .frame(maxWidth: .infinity) .background(Color.black) .padding(.vertical, 20) .ignoresSafeArea() .navigationBarHidden(hideNavigationBar) .toolbarBackground(.visible, for: .navigationBar) .simultaneousGesture(TapGesture().onEnded { print("Tapped") })
内容的提问来源于stack exchange,提问作者Deepak Sharma
相关产品推荐
相关产品推荐

