SwiftUI中WKWebView允许文本选中但隐藏上下文菜单的实现方法
解决方案
要实现保留WKWebView文本选中的蓝色手柄,但禁用上下文菜单,可以通过以下两步完成,核心是正确配置WKWebView代理并拦截网页自定义菜单事件:
1. 移除禁用文本选中的JavaScript
你之前注入的CSS代码-webkit-user-select:none会直接禁用文本选中功能,不符合需求,必须删除这段JS。
2. 配置WKWebView代理拦截系统上下文菜单 + 阻止网页自定义菜单
在你的UIViewRepresentable实现中,需要正确设置WKUIDelegate,并注入JS阻止网页自带的长按菜单事件:
import SwiftUI import WebKit struct WebView: UIViewRepresentable { let url: URL func makeUIView(context: Context) -> WKWebView { let configuration = WKWebViewConfiguration() let webView = WKWebView(frame: .zero, configuration: configuration) // 设置代理,确保拦截上下文菜单的方法生效 webView.uiDelegate = context.coordinator webView.navigationDelegate = context.coordinator // 注入JS阻止网页自定义的上下文菜单事件 let disableCustomMenuJS = "document.addEventListener('contextmenu', e => e.preventDefault());" webView.evaluateJavaScript(disableCustomMenuJS, completionHandler: nil) return webView } func updateUIView(_ uiView: WKWebView, context: Context) { uiView.load(URLRequest(url: url)) } func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate { // 拦截系统上下文菜单,返回nil表示不显示菜单 func webView(_ webView: WKWebView, contextMenuConfigurationForElement elementInfo: WKContextMenuElementInfo, completionHandler: @escaping (UIContextMenuConfiguration?) -> Void) { completionHandler(nil) } // 可选:完全禁用预览弹窗(如果不需要的话) func webView(_ webView: WKWebView, previewViewControllerForElement elementInfo: WKContextMenuElementInfo, defaultPreviewViewController: UIViewController?) -> UIViewController? { return nil } } }
关键说明
- 之前你的代理方法没生效,是因为没有将WKWebView的
uiDelegate指向Coordinator,导致系统不会调用你的拦截方法。 - 注入的JS用于阻止网页自身实现的
contextmenu事件(部分网页会自定义长按菜单),确保全面禁用菜单。 - 此方案不会影响文本选中功能,用户依然可以长按选中文本并通过蓝色手柄调整选中文本范围。
内容的提问来源于stack exchange,提问作者km11
相关产品推荐
相关产品推荐

