You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 15:41:14