针对 WebView 强制使用本地字体的完整解决方案
针对 WebView 强制使用本地字体的完整解决方案,需要从 字体加载机制、CSS 注入时机 和 兼容性处理 三个维度进行优化。以下是分步骤的终极方案:
一、核心方案:拦截网络请求替换字体(100% 覆盖)
通过 shouldInterceptRequest 拦截所有字体请求,直接返回本地字体文件:
YourActivity.java
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString().toLowerCase();
// 拦截所有字体请求(支持常见字体格式)
if (url.endsWith(".ttf") || url.endsWith(".otf") || url.endsWith(".woff") || url.endsWith(".woff2")) {
try {
// 从 assets 加载本地字体文件(示例:替换所有请求为同一个字体)
InputStream is = getAssets().open("fonts/YourFont.ttf");
return new WebResourceResponse("font/ttf", "UTF-8", is);
} catch (IOException e) {
e.printStackTrace();
}
}
return super.shouldInterceptRequest(view, request);
}
@Override
public void onPageFinished(WebView view, String url) {
// 补充 CSS 强制覆盖(防止网页内联样式覆盖)
String css = "*:not([class*='icon']):not([class*='symbol']) { " +
"font-family: 'YourFont' !important; " +
"}";
String js = "(function() {" +
"var style = document.createElement('style');" +
"style.innerHTML = '" + css + "';" +
"document.head.appendChild(style);" +
"})()";
view.evaluateJavascript(js, null);
}
});
---
二、关键增强措施
1. 字体格式兼容性处理
修改 shouldInterceptRequest 中返回的 MIME 类型:
// 根据实际文件类型返回正确的 MIME
String mimeType = "font/woff";
if (url.endsWith(".ttf")) mimeType = "font/ttf";
else if (url.endsWith(".otf")) mimeType = "font/otf";
2. 多字体策略(针对不同文字类型)
// 根据请求路径返回不同字体
if (url.contains("zh") || url.contains("chinese")) {
return new WebResourceResponse(..., getAssets().open("fonts/zh_font.ttf"));
} else {
return new WebResourceResponse(..., getAssets().open("fonts/en_font.ttf"));
}
3. 防缓存污染
在 WebView 设置中禁用缓存:
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
---
三、终极保障方案
1. 字体预加载策略
在 WebView 初始化时提前注入字体定义:
String preloadJS = "var style = document.createElement('style');" +
"style.textContent = '@font-face { font-family: YourFont; src: url(\"file:///android_asset/fonts/YourFont.ttf\"); }';" +
"document.head.appendChild(style);";
webView.evaluateJavascript(preloadJS, null);
- 暴力 DOM 更新
定时检查并强制更新字体:
String watchdogJS = "setInterval(function() {" +
"document.querySelectorAll('*').forEach(el => {" +
"el.style.fontFamily = 'YourFont !important';" +
"})" +
"}, 1000);";
webView.evaluateJavascript(watchdogJS, null);
四、调试技巧
1. 启用 WebView 调试
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
通过 Chrome 的 chrome://inspect 实时调试
2. 日志监控
在 shouldInterceptRequest 中添加日志:
Log.d("FONT_INTERCEPT", "Intercepted font request: " + url);
五、注意事项
1. 字体授权
确保本地字体文件有合法的使用授权
2. 性能优化
大字体文件建议使用 woff2 格式并压缩
- 排除图标字体
在 CSS 选择器中添加排除规则(示例中已包含 :not([class*='icon']))
此方案通过 请求拦截 + CSS 注入 + DOM 监控 三重保障,可应对 99% 的网页场景。若仍有个别元素未被覆盖,可通过 Chrome 远程调试具体分析元素样式优先级。