Jetpack Compose GoogleMap中MarkerComposable抛出尺寸异常问题
从传统XML+ClusterRenderer切换到GoogleMap Composable后,创建了ClusterMarker组件用于显示带集群数量的标记图钉,但运行时抛出异常:
java.lang.IllegalStateException: The ComposeView was measured to have a width or height of zero. Make sure that the content has a non-zero size.
即使在Box中设置了固定宽高(40dp×47dp),仍触发该异常,相关代码如下:
@Composable fun BaseClusterMarker( size: Int, position: LatLng, ) { val markerState = rememberMarkerState(position = position) MarkerComposable( state = markerState, content = { Box( modifier = Modifier .size( width = 40.dp, height = 47.dp, ), contentAlignment = Alignment.Center, ) { Image( modifier = Modifier .matchParentSize(), painter = painterResource(id = R.drawable.map_pin), contentDescription = "", ) Text( modifier = Modifier .align(Alignment.Center), color = MainTheme.colors.main.mapColors.pinTextColor, text = size.toString(), style = MainTheme.typography.text.medium.bold, maxLines = 1, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, ) } }, ) }
排查与解决方案
这个异常的核心原因是MarkerComposable的content在初始测量阶段没有拿到有效的尺寸约束,即使给Box设置了固定size,也可能因为ComposeView和Google Maps的测量时机不匹配导致失效。可以从以下几个方向修复:
显式设置MarkerComposable的宽高参数:MarkerComposable本身提供了
width和height参数,直接指定这两个参数而非仅在内部Box设置,让Google Maps提前知道ComposeView的预期尺寸:MarkerComposable( state = markerState, width = 40.dp, height = 47.dp, content = { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center, ) { Image( modifier = Modifier.fillMaxSize(), painter = painterResource(id = R.drawable.map_pin), contentDescription = "Cluster pin" ) Text( modifier = Modifier.align(Alignment.Center), color = MainTheme.colors.main.mapColors.pinTextColor, text = size.toString(), style = MainTheme.typography.text.medium.bold, maxLines = 1, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, ) } } )检查Image资源加载状态:如果
R.drawable.map_pin资源不存在、加载失败或尺寸为0,会导致布局坍缩。可以临时替换为纯色Box测试,若异常消失则说明是资源问题:Box( modifier = Modifier .size(40.dp, 47.dp) .background(Color.Red), contentAlignment = Alignment.Center ) { Text(size.toString()) }替换matchParentSize为fillMaxSize:
matchParentSize依赖父布局的已确定尺寸,但MarkerComposable初始父布局尺寸可能未稳定,fillMaxSize会直接占满父布局分配的空间,更可靠。排查主题/排版配置:若
MainTheme.typography.text.medium.bold的字体大小为0,或Text颜色透明且无其他可见内容,也可能导致布局尺寸为0。临时替换为默认TextStyle测试是否恢复正常:Text( text = size.toString(), style = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Bold), maxLines = 1, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, color = Color.Black )
内容的提问来源于stack exchange,提问作者Martin

