Android WebView 深色模式適配方案總結
在 Android WebView 中適配深色模式(Dark Mode)是一個常見的需求,尤其是當加載的網頁沒有原生支持 prefers-color-scheme
時。本文將介紹 3 種主流方案,并分析它們的優缺點,幫助開發者選擇最佳實現方式。
方案 1:JS 動態注入 CSS(適合任意網頁)
核心思路
通過 JavaScript 動態插入 CSS,強制修改網頁的背景、文字顏色等樣式。
代碼實現(Kotlin)
fun applyDarkMode(webView: WebView, isDarkMode: Boolean) {val css = if (isDarkMode) {"""html, body, body * {background-color: #1a1a1a !important;color: #e0e0e0 !important;}/* 隱藏某些元素 */#ad-container { display: none !important; }"""} else {"""html, body, body * {background-color: #ffffff !important;color: #000000 !important;}"""}val js = """var style = document.createElement('style');style.innerHTML = `${css.replace("\n", "")}`;document.head.appendChild(style);""".trimIndent()webView.evaluateJavascript(js, null)
}
調用時機
webView.webViewClient = object : WebViewClient() {override fun onPageFinished(view: WebView?, url: String?) {applyDarkMode(webView, isDarkMode)}
}
優缺點
? 優點:
- 適用于任何網頁(包括第三方網頁)。
- 可精細控制特定元素的樣式(如隱藏廣告)。
? 缺點:
- 可能受 CSP(內容安全策略)限制,導致注入失敗。
- 部分網頁可能因 CSS 優先級問題無法覆蓋默認樣式。
方案 2:強制 WebView 深色渲染(API 29+)
核心思路
Android 10 (API 29) 引入了 WebSettingsCompat.FORCE_DARK
,可讓 WebView 自動適配深色模式。
代碼實現
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {WebSettingsCompat.setForceDark(webView.settings,if (isDarkMode) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF)
}
適配網頁
網頁需支持 prefers-color-scheme
:
/* 深色模式適配 */
@media (prefers-color-scheme: dark) {body {background: #121212;color: #f0f0f0;}
}
優缺點
? 優點:
- 系統級支持,兼容性較好(適用于支持
prefers-color-scheme
的網頁)。 - 無需手動注入 CSS,減少代碼維護成本。
? 缺點:
- 僅適用于 API 29+。
- 如果網頁未適配
prefers-color-scheme
,可能渲染異常。
方案 3:攔截并修改網頁內容(高級方案)
核心思路
通過 WebViewClient.shouldInterceptRequest
攔截 HTML/CSS,動態替換樣式。
代碼示例
webView.webViewClient = object : WebViewClient() {override fun shouldInterceptRequest(view: WebView?,request: WebResourceRequest?): WebResourceResponse? {if (request?.url?.toString()?.endsWith(".css") == true) {// 修改 CSS 內容val darkCss = """body { background: #1a1a1a !important; }""".trimIndent()return WebResourceResponse("text/css","UTF-8",ByteArrayInputStream(darkCss.toByteArray()))}return super.shouldInterceptRequest(view, request)}
}
優缺點
? 優點:
- 可深度定制網頁樣式,甚至替換整個 CSS 文件。
- 不受 CSP 限制,適用于嚴格安全策略的網頁。
? 缺點:
- 實現復雜,需處理各種資源加載情況。
- 可能影響網頁功能(如動態加載的樣式)。
最佳實踐推薦
方案 | 適用場景 | 兼容性 | 實現難度 |
---|---|---|---|
JS 注入 CSS | 任意網頁,需動態調整樣式 | 所有版本 | ?? |
WebView 強制深色 | 網頁已支持 prefers-color-scheme | API 29+ | ? |
攔截修改網頁 | 需要深度定制樣式 | 所有版本 | ??? |
推薦方案
- 優先檢查網頁是否支持
prefers-color-scheme
,如果支持,使用 方案 2(FORCE_DARK
)。 - 如果網頁不受控(如第三方頁面),使用 方案 1(JS 注入 CSS)。
- 如果需要更高級控制(如企業定制頁面),可嘗試 方案 3(攔截修改)。
總結
在 Android WebView 中實現深色模式,主要有 動態注入 CSS、系統強制深色渲染 和 攔截修改網頁 三種方式。選擇方案時需考慮:
- 網頁是否可控(能否修改 CSS?)
- Android 版本兼容性(是否需要支持舊版?)
- 是否需要精細控制(如隱藏廣告、修改字體等)
如果你的網頁可控,建議直接使用 prefers-color-scheme
+ FORCE_DARK
;如果是第三方網頁,JS 注入 CSS 是最穩妥的方案。