android webview 黑屏问题
What(做了什么)
在 Flayp Signage 内嵌的 WebView(MainActivity.kt → PlayerWebView)上增加了三类行为:
-
layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)明确与全屏容器一致的测量意图(贴近系统 WebView Browser Tester 在
Activity+FrameLayout中的写法)。 -
onPageFinished→post { evaluateJavascript(...) }在页面加载完成后,向页面注入一次
window.dispatchEvent(new Event('resize')),促使页面内联的setRem()(随resize重新计算根字号)再执行。 -
attachRemReflowOnceWhenSized()通过
View.OnLayoutChangeListener,在 第一次 出现width > 0 && height > 0时再触发一次上述resize,然后移除监听(只执行一次)。
此外,与 H5 自带 <meta name="viewport" ...> 配合时,已保持:
settings.useWideViewPort = truesettings.loadWithOverviewMode = false
避免「整页缩成概览」导致主体区域像被挤出可视区(与 Tester 的默认缩放策略更一致)。
Why(为什么 / 解决什么问题)
现象
- 同一 URL(如
game-place-view/admin.html)在 WebView Browser Tester 或系统浏览器中 列表、比分正常; - 在 Flayp 里 often 仅蓝条标题可见,下方大面积黑色 ,而 logcat 里 XMDS / WebSocket / STOMP MESSAGE 仍正常。
根因归纳
| 对比项 | WebView Browser Tester | Flayp(Compose) |
|---|---|---|
| 容器 | 传统 Activity,WebView 多为 MATCH_PARENT 一次量准 |
AndroidView 嵌入 Box,首帧常出现宽/高为 0 再变为全屏 |
| 页面逻辑 | 内联 setRem() 依赖 document.documentElement.clientWidth / window.innerWidth |
若在 视口仍为 0×0 或未稳定 时跑过 setRem() ,rem 基准会错 ,导致 #app 下列表区域高度/缩放异常,视觉上像「只有头、下面全黑」 |
因此问题不首先是「没数据」 ,而是 Compose 测量时序 + 页面 rem 适配 叠加后的 渲染布局问题。
Where(改在哪里)
- 文件 :
app/src/main/java/com/flayp/signage/MainActivity.kt - 位置 :
PlayerWebView中 iframe 分支 (loadUrl)与loadDataWithBaseURL分支 的WebView初始化处;以及文件内私有扩展/方法:WebView.requestRemReflowAfterLayout()WebView.attachRemReflowOnceWhenSized()
When(何时会触发 reflow)
| 时机 | 作用 |
|---|---|
onPageFinished |
文档声明加载完成后再 post 触发 resize,给 setRem 一次机会。 |
| 首次 layout 宽高为正 | 覆盖 先 onPageFinished、后 Compose 才把 WebView 拉大 的顺序,避免永远停留在错误 rem。 |
How(如何实现)
-
evaluateJavascript执行最小脚本:
(function(){ try { window.dispatchEvent(new Event('resize')); } catch(e) {} })();复用页面已有的
window.addEventListener('resize', setRem),不依赖页面导出全局函数名。 -
post { ... }保证在 UI 线程下一帧 执行,避免与 WebView 内部布局竞争。 -
OnLayoutChangeListener在宽高有效后触发一次再 remove,避免重复抖动与多余 JS 调用。
验证建议
assembleDebug安装到 API 31+ 模拟器或真机 ,横屏对比 Flayp 与 WebView Browser Tester 同一 URL。chrome://inspect:必要时对比 Console / Elements 中#app高度与根字号。- 若仅老系统 WebView(如 Chrome 51 级别)仍白屏,需另论 ES 语法兼容性 (与
minSdk/ 系统 WebView 升级相关),不在本文 reflow 改动范围内。
相关历史改动(简述)
loadWithOverviewMode = false:与带viewport的 H5 配合,避免整页被缩成「概览」后主体不可见。- 国内 Gradle/Maven 镜像、
buildToolsVersion等:属构建环境,与页面 reflow 无关,不展开。