Android的webview将容器改尺寸传给html以便html适配
at 2023-03-31 21:07:25, by 鹏城奋青
载有高德地图的html中,容器或其父级必须给定具体尺寸,否则在webview中嵌入时不会有任何显示。
因此我们在Android View确定尺寸时,调用外部js将尺寸传过去,实践发现得先转为dp值才正确。
@Composable
fun Map() {
var progress by remember { mutableStateOf(0) }
var lng by remember { mutableStateOf(0.0) }
var lat by remember { mutableStateOf(0.0) }
var done by remember { mutableStateOf(false) }
var size by remember { mutableStateOf(IntSize.Zero) }
Box(modifier = Modifier
.fillMaxWidth()
.weight(1f)) {
AndroidView(
factory = {
WebView(it).apply {
wv = this
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.databaseEnabled = true
settings.blockNetworkImage = false
settings.blockNetworkLoads = false
settings.loadsImagesAutomatically = true
settings.allowUniversalAccessFromFileURLs = true
settings.allowFileAccessFromFileURLs = true
settings.allowFileAccess = true
settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView?, newProgress: Int) {
progress = newProgress
}
}
webViewClient = object: WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
done = true
}
}
class Bridge {
@JavascriptInterface
fun locationUpdate(lg: Double, lt: Double) {
lng = lg
lat = lt
}
}
addJavascriptInterface(Bridge(), "bridge")
loadUrl(
Chatty.getLocationChooseUrl(
longitude = locationData.longitude,
latitude = locationData.latitude
)
)
}
},
modifier = Modifier
.fillMaxSize()
.onSizeChanged { size = it },
) {
it.webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView?, newProgress: Int) {
progress = newProgress
}
}
}
val density = LocalDensity.current
LaunchedEffect(done, size) {
if (done) {
val w = with(density) { size.width.toDp().value.toInt() }
val h = with(density) { size.height.toDp().value.toInt() }
wv?.evaluateJavascript(
"onSizeChanged(${w},${h})",
null
)
}
}
}
}
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<style>
html, body, #container {
margin: 0;
background-color: gray;
width: 100%;
height: 100%;
}
#marker {
position: fixed;
width: 20px;
height: 26px;
z-index: 999;
left: 50%;
top: 50%;
transform: translate(-10px, -26px);
}
#info {
position: fixed;
z-index: 1000;
left: 50%;
top: 50%;
transform: translateY(30px);
}
</style>
</head>
<body id="body">
<img id="marker" src="//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png"/>
<div id="container"></div>
<div id="info"></div>
<script src="//webapi.amap.com/maps?v=2.0&key={{.key}}"></script>
<script>
const pos = new AMap.LngLat({{.longitude}},{{.latitude}});
const map = new AMap.Map("container", {
viewMode: '2D',
center: pos,
zoom: 15,
keyboardEnable: false,
jogEnable: false,
pitchEnable: false,
rotateEnable: false,
animateEnable: false,
keyboardEnable: false,
doubleClickZoom: false,
scrollWheel: false,
});
map.on('moveend', function () {
try {
const center = map.getCenter();
window.bridge.locationUpdate(center.lng, center.lat);
} catch (e) { }
});
function onSizeChanged(w,h) {
// 必须这样设置才行,在android webview中将容器尺寸转为dp再调用这个函数
const style = document.getElementById("body").style
style.width = w+"px";
style.height = h+"px";
}
</script>
</body>
</html>