如何在WKWebView中监听视频全屏进入/退出事件并处理?
如何在WKWebView中检测视频全屏状态变化
嘿,针对你需要检测WKWebView里视频进入/退出全屏、并执行对应界面逻辑的需求,完全可以通过观察者(Notification Center)来实现,这是iOS里处理这类系统级事件的常规操作,另外还有JS交互的方案供你选择,下面给你详细拆解:
一、用系统通知(观察者)实现
1. 需要捕获的关键通知
你需要监听两个全局通知,它们是视频全屏状态变化时系统会自动发出的:
UIWindowDidBecomeVisibleNotification:视频进入全屏时,系统会创建一个单独的全屏UIWindow来播放视频,这个通知会触发UIWindowDidBecomeHiddenNotification:视频退出全屏时,那个全屏窗口会被隐藏,对应这个通知
不过要注意,这两个通知是全局的,所以得在回调里加个判断,确保是WKWebView相关的视频窗口,避免误触发其他全屏事件。
2. 具体代码实现
注册通知观察者
在你的视图控制器的viewDidLoad里注册这两个通知:
override func viewDidLoad() { super.viewDidLoad() // 监听视频进入全屏 NotificationCenter.default.addObserver( self, selector: #selector(onVideoEnterFullScreen(_:)), name: UIWindow.didBecomeVisibleNotification, object: nil ) // 监听视频退出全屏 NotificationCenter.default.addObserver( self, selector: #selector(onVideoExitFullScreen(_:)), name: UIWindow.didBecomeHiddenNotification, object: nil ) }
实现通知回调
在回调里判断窗口是否是AVPlayer的全屏播放窗口:
@objc private func onVideoEnterFullScreen(_ notification: Notification) { guard let window = notification.object as? UIWindow else { return } // 判断是否是苹果原生的全屏视频控制器窗口 let avFullScreenVCClass = NSClassFromString("AVFullScreenViewController") ?? NSObject.self if window.rootViewController?.isKind(of: avFullScreenVCClass) ?? false { // 这里写你要执行的进入全屏逻辑,比如展示特定选项、修改界面 print("视频进入全屏啦!") } } @objc private func onVideoExitFullScreen(_ notification: Notification) { guard let window = notification.object as? UIWindow else { return } let avFullScreenVCClass = NSClassFromString("AVFullScreenViewController") ?? NSObject.self if window.rootViewController?.isKind(of: avFullScreenVCClass) ?? false { // 这里写退出全屏后的逻辑 print("视频退出全屏啦!") } }
移除观察者(避免内存泄漏)
记得在视图控制器销毁时移除观察者:
deinit { NotificationCenter.default.removeObserver(self) }
二、用JS交互实现(更精准)
如果你觉得全局通知不够精准,或者能控制网页内容,那可以通过注入JavaScript的方式,让网页主动通知Native视频的全屏状态变化:
1. 配置WKWebView并注入JS
在你的loadWebSite方法里添加脚本处理器和注入监听代码:
func loadWebSite() { let configuration = WKWebViewConfiguration() let preferences = WKPreferences() preferences.javaScriptCanOpenWindowsAutomatically = true configuration.preferences = preferences // 添加脚本消息处理器,用于接收网页发来的消息 configuration.userContentController.add(self, name: "videoFullScreenHandler") // 注入JS代码,监听网页的全屏事件 let fullScreenJS = """ // 监听标准全屏事件 document.addEventListener('fullscreenchange', function() { if (document.fullscreenElement) { window.webkit.messageHandlers.videoFullScreenHandler.postMessage('enter'); } else { window.webkit.messageHandlers.videoFullScreenHandler.postMessage('exit'); } }); // 兼容Safari/webkit的全屏事件前缀 document.addEventListener('webkitfullscreenchange', function() { if (document.webkitFullscreenElement) { window.webkit.messageHandlers.videoFullScreenHandler.postMessage('enter'); } else { window.webkit.messageHandlers.videoFullScreenHandler.postMessage('exit'); } }); """ let userScript = WKUserScript( source: fullScreenJS, injectionTime: .atDocumentEnd, forMainFrameOnly: true ) configuration.userContentController.addUserScript(userScript) // 初始化并添加WKWebView到视图 let webView = WKWebView(frame: view.bounds, configuration: configuration) view.addSubview(webView) // 加载你的网页... webView.load(URLRequest(url: URL(string: "your-web-url")!)) }
2. 实现WKScriptMessageHandler协议
让你的视图控制器遵守协议,处理网页发来的消息:
extension YourViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard let status = message.body as? String else { return } switch status { case "enter": // 视频进入全屏逻辑 print("网页通知:视频进入全屏") case "exit": // 视频退出全屏逻辑 print("网页通知:视频退出全屏") default: break } } }
三、两种方案怎么选?
- 系统通知方案:不需要修改网页代码,适合你无法控制网页内容的场景,但需要做窗口类型判断避免误触发
- JS交互方案:只响应当前WKWebView内的视频事件,更精准,但需要网页支持(或者你能注入JS代码)
这两种方案都能完美满足你修改界面、展示特定选项的需求,根据你的实际场景选就行~
内容的提问来源于stack exchange,提问作者ÉnnOâman
相关产品推荐
相关产品推荐

