kotlin+ compose + webview H5页面 100%高度为0解决
最近在做kotlin+compose 项目里内嵌webview渲染web页面的功能,但是遇到了不少麻烦问题,正好记录下。
问题: webview 的H5页面html的 高度始终为0,无法撑满页面,最后用浏览器调试发现是web项目有一个这样的样式定义,而webviw初始化的时候是拿不到内容的真实高度的
html, body {
height: 100%
}
所以其实问题也不在web项目,是在kotlin compose自动计算webview高度的时候,会先获取内容高度去计算怎么适配大小,但是因为100%这时候又无法获取真实的高度,所以webview里的html实际高度为0(感觉根本应该是这个问题,有知道的大佬也可以分享一下)
解决:给webview一个真实的高度,有两种方式
第一种方式: 获取webview的父节点剩余高度并赋值给webview, 思路就是套一个Box上设置weight(1f), 就会占据父节点剩余的高度, 参考代码【当然,如果全占满就不需要包一个box了】
var availableHeight by remember { mutableIntStateOf(0) }
Column(modifier = modifier.fillMaxSize()) {
Text(
text = title,
fontSize = 26.sp
)
// 用Compose剩余高度设置
Box( modifier = Modifier
.weight(1f)
.onGloballyPositioned { coordinates ->
availableHeight = coordinates.size.height
}
) {
if(availableHeight > 0) {
AndroidView(
factory = {
WebView(getApplication<Application>()).apply{
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
availableHeight // 强制指定像素高度
)
}
},
)
}
}
}
第二种方式:获取屏幕高度减去安全区域高度和其他被占用的高度,参考代码
val configuration = LocalConfiguration.current
val screenHeight = with(LocalDensity.current) {
configuration.screenHeightDp.dp.toPx().toInt()
}
// 减去系统栏(可选)
// val statusBar = WindowInsets.statusBars.getTop(density)
// val navBar = WindowInsets.navigationBars.getBottom(density)
// val safeHeight = screenHeightPx - statusBar - navBar
AndroidView(
modifier = Modifier.fillMaxSize()
factory = {
WebView(getApplication<Application>()).apply{
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
screenHeight // 强制指定像素高度
)
}
},
)
感觉还是第一种方式方便点,起码不用考虑减去其他高度
另外, 要让webview的内容高度正常,需要确认下面几步是否都正确:
- 确认H5页面在浏览器内可以正常打开
- 检查h5是否有定义viewport并且设置了width="device-width"
- 是否有可能的http请求报错(一般h5能打开 + 允许http配置是没有问题的)
- 对应的父compose节点是否有高度(一般是fillMaxSize或者fillMaxHeight)
- webview里的url不能是http(可以在Manifest文件里配置强制开通, 配置步骤附在后面)
- 写一段测试html查看webview是否能正确显示(测试代码附在后面)
- 用chrome浏览器辅助调试,查看H5页面的dom是否有正常显示(测试步骤附在后面)
附:
- 允许http本地调试的配置:
如果需要http,需要在src/debug/res/xml文件夹下新建一个network_security_config.xml文件,在这里面设置允许http协议(注意: 放在debug文件下是因为只在
debug阶段本地测试,毕竟允许http是有风险的)。 然后src/debug/AndroidManifest.xml(没有的话就
新建)文件里引用该文件
network_security_config.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 允许指定域名所有明文流量(仅限调试!) -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">线上测试http地址.com</domain>
</domain-config>
<!-- 允许本机所有明文流量(仅限调试!) -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
AndroidManifest.xml:文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>
2. 测试代码,用于验证webview配置是否正确
LaunchedEffect(Unit) {
val html = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { background: lightblue; margin: 20px; }
h1 { color: red; font-size: 24px; }
</style>
</head>
<body>
<h1>✅ WebView 测试成功!</h1>
<p>如果看到这个,说明 WebView 配置正确。</p>
</body>
</html>
""".trimIndent()
webview.loadDataWithBaseURL(null, html, "text/html", "utf-8", null)
3. 配置浏览器调试
- Android 端进入到需要调试的界面
- 浏览器打开chrome://inspect/#devices,点开Configure(配置)输入ip地址, 例如: http://192.160.0.0:4030/等一会就会出现你要调试的设备信息,点击inspect就可以像浏览器调试那样去调试了

更多推荐


所有评论(0)