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

如何在Google Map上显示多个信息窗口?Android端技术实现问询

嘿,我刚好处理过类似的需求!Google Maps Android SDK确实没有原生支持同时显示多个信息窗口,但我们可以通过自定义View绕过原生机制来实现,下面是具体的实现方案:

Android Google Map 多信息窗口实现方案

核心思路

原生InfoWindow只能同时显示一个,所以我们需要自定义弹窗View,直接将其添加到Map的容器布局中,并绑定到对应Marker的屏幕位置上,以此模拟多窗口显示效果。

具体实现步骤

1. 编写自定义信息窗口布局

先创建一个你想要的信息窗口UI,比如命名为layout_custom_info_window.xml,可以根据需求添加标题、描述、图标等元素:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/info_window_bg"
    android:orientation="vertical"
    android:padding="12dp"
    android:elevation="8dp">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="@color/black"/>

    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:layout_marginTop="4dp"
        android:textColor="@color/dark_gray"/>
</LinearLayout>

2. 管理自定义窗口的状态

在你的Map页面(Activity/Fragment)中,定义变量来保存已显示的窗口和对应Marker的映射,方便后续更新或移除:

private val activeInfoWindows = mutableMapOf<Marker, View>()
private lateinit var googleMap: GoogleMap

3. 显示自定义信息窗口

不要调用原生的marker.showInfoWindow(),而是创建自定义View并添加到Map容器中,同时计算它的屏幕位置:

fun showCustomInfoWindow(marker: Marker) {
    // 避免重复创建同一Marker的窗口
    if (activeInfoWindows.containsKey(marker)) return

    // 加载自定义布局
    val infoView = LayoutInflater.from(this).inflate(R.layout.layout_custom_info_window, null)
    // 填充窗口内容
    infoView.findViewById<TextView>(R.id.tv_title).text = marker.title
    infoView.findViewById<TextView>(R.id.tv_desc).text = marker.snippet

    // 获取Map的容器布局(通常是SupportMapFragment的父View)
    val mapContainer = supportFragmentManager.findFragmentById(R.id.map_fragment)?.view as ViewGroup
    mapContainer.addView(infoView)

    // 计算窗口位置:将Marker经纬度转为屏幕坐标,调整位置让窗口在Marker上方
    val projection = googleMap.projection
    val markerScreenPos = projection.toScreenLocation(marker.position)
    val layoutParams = infoView.layoutParams as ViewGroup.MarginLayoutParams
    layoutParams.topMargin = markerScreenPos.y - infoView.height - 60 // 偏移量避免遮挡Marker
    layoutParams.leftMargin = markerScreenPos.x - infoView.width / 2 // 水平居中
    infoView.layoutParams = layoutParams

    // 保存到映射集合
    activeInfoWindows[marker] = infoView
}

4. 地图移动时更新窗口位置

当地图平移、缩放时,Marker的屏幕位置会变化,需要监听地图相机移动事件来更新所有窗口的位置:

googleMap.setOnCameraMoveListener {
    val projection = googleMap.projection
    activeInfoWindows.forEach { (marker, infoView) ->
        val markerScreenPos = projection.toScreenLocation(marker.position)
        val layoutParams = infoView.layoutParams as ViewGroup.MarginLayoutParams
        layoutParams.topMargin = markerScreenPos.y - infoView.height - 60
        layoutParams.leftMargin = markerScreenPos.x - infoView.width / 2
        infoView.layoutParams = layoutParams
    }
}

5. 关闭自定义窗口

实现单个窗口关闭和全部窗口关闭的方法:

// 关闭指定Marker的窗口
fun hideCustomInfoWindow(marker: Marker) {
    activeInfoWindows[marker]?.let { view ->
        (view.parent as ViewGroup).removeView(view)
        activeInfoWindows.remove(marker)
    }
}

// 关闭所有已显示的窗口
fun hideAllInfoWindows() {
    activeInfoWindows.values.forEach { view ->
        (view.parent as ViewGroup).removeView(view)
    }
    activeInfoWindows.clear()
}

6. 可选:添加窗口交互

如果需要给自定义窗口添加点击事件,直接在创建View时设置即可:

infoView.setOnClickListener {
    Toast.makeText(this, "点击了${marker.title}的信息窗口", Toast.LENGTH_SHORT).show()
    // 这里可以添加跳转详情页等逻辑
}

注意事项

  • 自定义窗口不会自动处理Marker的屏幕可见性,你可以通过googleMap.projection.visibleRegion判断Marker是否在视野内,不在则隐藏对应窗口
  • 如果Marker数量较多,建议复用View来避免频繁创建销毁带来的性能问题
  • 可以给窗口添加弹出、淡入等动画,提升用户体验

内容的提问来源于stack exchange,提问作者Sandip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:23:05