如何在Google Maps Compose中为路线起止点添加悬浮信息卡片
在Google Maps Compose中为路线起点/终点添加悬浮信息卡片
要实现路线起点、终点旁的悬浮信息卡片,核心是利用Compose的布局嵌套+地图坐标转换,将地理坐标(LatLng)转为屏幕坐标,从而精准定位卡片位置。以下是具体实现步骤:
1. 准备坐标转换工具
首先需要获取地图的投影(Projection),用于将路线的LatLng坐标转换为屏幕上的偏移量。可以通过地图的加载回调和相机移动事件更新投影:
val projection = remember { mutableStateOf<Projection?>(null) }
2. 构建自定义悬浮卡片组件
创建可复用的卡片Composable,用于展示时间、距离等信息:
@Composable fun RouteInfoCard( modifier: Modifier = Modifier, title: String, distance: String, duration: String ) { Card( modifier = modifier, elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), shape = RoundedCornerShape(8.dp) ) { Column( modifier = Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(4.dp) ) { Text(text = title, fontWeight = FontWeight.Bold) Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { Text(text = "距离: $distance") Text(text = "时长: $duration") } } } }
3. 整合到地图布局中
用Box将GoogleMap与悬浮卡片嵌套,通过投影转换坐标,动态计算卡片的位置:
Box(modifier = Modifier.fillMaxSize()) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState, properties = MapProperties( isMyLocationEnabled = true ), onMapLoaded = { map -> projection.value = map.projection }, onCameraMove = { projection.value = cameraPositionState.projection } ) { Marker( state = markerState, title = "Drop Off", ) if (route.isNotEmpty()) { val bitmapDescriptor = remember { bitmapDescriptorFromVector(context, R.drawable.ic_point) } Polyline( points = route, color = Color(0xFF1868D2), width = 14f, ) Polyline( points = route, startCap = CustomCap(bitmapDescriptor), endCap = CustomCap(bitmapDescriptor), color = Color(0xFF00B0FF), width = 10f, ) } } // 显示起点悬浮卡片 if (route.isNotEmpty() && projection.value != null) { val startLatLng = route.first() val startScreenPos = projection.value!!.toScreenLocation(startLatLng) RouteInfoCard( modifier = Modifier .offset( x = (startScreenPos.x - 120).dp, // 调整偏移避免遮挡标记 y = (startScreenPos.y - 80).dp ) .wrapContentSize(), title = "起点", distance = "5.2km", // 实际需通过Google Maps API计算 duration = "15分钟" ) // 显示终点悬浮卡片 val endLatLng = route.last() val endScreenPos = projection.value!!.toScreenLocation(endLatLng) RouteInfoCard( modifier = Modifier .offset( x = (endScreenPos.x - 120).dp, y = (endScreenPos.y - 80).dp ) .wrapContentSize(), title = "终点", distance = "5.2km", duration = "15分钟" ) } }
关键注意点
- 坐标实时更新:监听
onCameraMove回调,在地图拖动时重新计算屏幕坐标,确保卡片位置始终准确。 - 偏移调整:根据卡片实际尺寸调整
offset参数,避免卡片遮挡地图标记或路线。 - 数据来源:示例中的距离、时长为模拟值,实际开发中需通过Google Maps Directions API获取路线的真实距离和时长数据。
内容的提问来源于stack exchange,提问作者user924
相关产品推荐
相关产品推荐

