You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:25:30