Vue3 Capacitor Android WebView 虚拟导航栏遮挡问题与解决
在 Android 设备上运行 Capacitor 打包的 Vue 3 应用时,经常会遇到虚拟导航栏(底部返回键、主页键等)和状态栏遮挡应用内容的问题。这不仅影响美观,还可能导致交互区域失效。
问题表现
- 底部 Tab 导航栏被虚拟导航栏遮挡一部分
- 顶部内容被状态栏遮挡
- 页面底部内容贴近虚拟导航栏,缺乏安全间距
问题根源分析
初始状态
应用使用了沉浸式布局,在 MainActivity.java 中设置了全屏透明:
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
这使得 WebView 内容延伸到状态栏和导航栏后面,实现了视觉上的全屏显示,但也带来了内容重叠的风险。
CSS 环境变量的误区
最初尝试使用 CSS 的环境变量来解决:
padding-top: env(safe-area-inset-top, 0);
padding-bottom: env(safe-area-inset-bottom, 0);
问题在于:Android WebView 对 CSS 的 env(safe-area-inset-*) 环境变量支持并不完善。
通过调试日志验证:
const rootStyles = getComputedStyle(document.documentElement);
console.log('CSS 环境变量原始值:', {
'safe-area-inset-top': rootStyles.getPropertyValue('safe-area-inset-top'),
'safe-area-inset-bottom': rootStyles.getPropertyValue('safe-area-inset-bottom')
});
实验结果显示,这些变量在 Android WebView 中通常返回空字符串。之前看到的 padding 效果其实是 CSS 中硬性编码的数值在起作用,而 fallback 值 0 导致没有底部间距。
最终解决方案
既然 CSS 环境变量不生效,我们改用 JavaScript 在运行时动态计算安全区域高度,并通过 CSS 变量传递给样式层。
1. JavaScript 动态计算
在 src/main.ts 中添加适配逻辑。这里选择估算而非精确获取,是为了减少依赖插件带来的复杂度。

