悠悠楠杉
在Swift中为WKWebView动态HTML内容实现暗黑模式文本与背景色切换,swiftui html
在Swift中为WKWebView动态HTML内容实现暗黑模式文本与背景色切换
要实现这一功能,核心思路是在原生层监听系统外观变化,并将当前界面模式通过JavaScript注入的方式传递给WKWebView中的HTML页面,从而动态调整其CSS样式。整个过程涉及Swift与JavaScript的交互、KVO观察机制以及CSS类的灵活控制。
首先,在Swift端需要创建一个WKWebView实例并配置其基本行为。通常我们会将WKWebView作为视图控制器的一部分进行管理。为了实时响应系统外观变更,可以利用KVO(键值观测)来监听traitCollection.userInterfaceStyle属性的变化:
swift
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView(frame: view.bounds)
view.addSubview(webView!)
// 加载本地HTML内容或远程URL
if let url = Bundle.main.url(forResource: "content", withExtension: "html") {
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
}
// 监听界面风格变化
self.observe(\.traitCollection.userInterfaceStyle, options: [.new]) { [weak self] _, change in
self?.updateWebViewAppearance()
}
}
当系统主题发生变化时,调用updateWebViewAppearance()方法。该方法的作用是判断当前是否为暗黑模式,并通过evaluateJavaScript向网页注入相应的脚本:
swift
private func updateWebViewAppearance() {
let isDarkMode = traitCollection.userInterfaceStyle == .dark
let script = "setTheme('\(isDarkMode ? "dark" : "light")')"
webView?.evaluateJavaScript(script)
}
接下来的关键在于HTML页面内部的JavaScript处理逻辑。我们需要提前在HTML文件中定义好setTheme函数,并设置对应的CSS类来控制颜色方案。例如,在<head>中加入如下样式:
html
这里的CSS过渡效果让颜色切换更加平滑自然,避免突兀的闪烁。同时,通过添加或移除dark-mode类,实现了样式的动态更新。
值得注意的是,如果HTML内容来自远程服务器且无法修改源码,则可以在Swift中构建内联脚本,通过WKUserScript方式提前注入JavaScript代码。这样即使页面重新加载,主题控制逻辑依然有效:
swift
let source = """
function setTheme(mode) {
document.body.className = mode === 'dark' ? 'dark-mode' : '';
}
setTheme('(traitCollection.userInterfaceStyle == .dark ? "dark" : "light")');
"""
let userScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
webView.configuration.userContentController.addUserScript(userScript)
此外,还需考虑首次加载时的主题匹配问题。若未手动触发一次主题设置,可能会出现短暂的样式错乱。因此建议在页面加载完成后立即根据当前模式执行一次注入。
最终效果是:无论用户在阅读过程中切换系统设置,还是App启动时即处于暗黑模式,WKWebView中的文字与背景都能无缝适配,提供一致且舒适的阅读体验。这种原生与Web技术的深度融合,正是现代混合式应用开发的重要体现。
