Flutter InAppWebView不跟随系统主题问题求助
解决InAppWebView加载网页不跟随系统主题切换的问题
核心原因
多数网站(包括谷歌)依赖系统主题偏好信号或请求头标识来切换深色/浅色模式,但InAppWebView默认不会主动传递这些信息,导致网页无法感知系统主题变化。
具体解决方案
1. 配置WebView的系统主题同步
根据平台(Android/iOS)设置WebView的强制深色模式,同步系统主题状态:
Flutter 代码示例
import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; class WebViewPage extends StatefulWidget { @override _WebViewPageState createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> with WidgetsBindingObserver { late InAppWebViewController webViewController; bool isDarkMode = false; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // 初始化时获取当前主题 isDarkMode = MediaQuery.of(context).platformBrightness == Brightness.dark; } @override void didChangePlatformBrightness() { // 监听系统主题变化 setState(() { isDarkMode = MediaQuery.of(context).platformBrightness == Brightness.dark; }); // 更新WebView主题配置 _updateWebViewTheme(); super.didChangePlatformBrightness(); } void _updateWebViewTheme() async { if (webViewController == null) return; // Android 配置:强制深色模式 if (await WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) { await webViewController.setForceDark( isDarkMode ? ForceDark.FORCE_DARK_ON : ForceDark.FORCE_DARK_OFF ); } // iOS 配置:设置内容偏好模式 await webViewController.setPreferences( preferences: InAppWebViewPreferences( preferredContentMode: isDarkMode ? UserInterfaceContentMode.DARK : UserInterfaceContentMode.LIGHT ) ); // 重载网页使配置生效 await webViewController.reload(); } @override Widget build(BuildContext context) { return Scaffold( body: InAppWebView( initialUrlRequest: URLRequest(url: Uri.parse("https://www.google.com")), onWebViewCreated: (controller) => webViewController = controller, initialSettings: InAppWebViewSettings( // 基础配置 javaScriptEnabled: true, useShouldOverrideUrlLoading: true, ), ), ); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } }
2. 注入主题偏好请求头
直接在请求中添加Sec-CH-Prefers-Color-Scheme头,明确告诉网站用户的主题偏好:
// 在initialUrlRequest中添加请求头 initialUrlRequest: URLRequest( url: Uri.parse("https://www.google.com"), headers: { 'Sec-CH-Prefers-Color-Scheme': isDarkMode ? 'dark' : 'light' } ),
如果需要动态适配主题变化,可以在didChangePlatformBrightness中重新加载网页并更新请求头。
3. 注入JS强制切换网页主题
如果前两种方法无效,可以通过JS直接修改网页的主题状态(以谷歌页面为例):
void _forceWebTheme() async { if (webViewController == null) return; String jsCode = isDarkMode ? """ // 模拟点击谷歌的深色模式切换按钮 document.querySelector('button[aria-label="深色主题"]')?.click(); """ : """ document.querySelector('button[aria-label="浅色主题"]')?.click(); """; await webViewController.evaluateJavascript(source: jsCode); }
注意事项
- 不同网站的主题切换逻辑不同,部分网站可能只支持其中一种方式,需要按需测试;
- Android的
FORCE_DARK需要WebView 83+版本支持,低版本可能需要降级处理; - 监听主题变化时,务必在
dispose中移除观察者,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Jesse
相关产品推荐
相关产品推荐

