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

如何为Mapbox中所有标记添加点击事件并显示对应地址?

解决Mapbox多标记点击事件仅单个生效的问题

问题根源

你的代码存在三个核心问题:

  • 循环中每次创建新的PointAnnotationManager,导致只有最后一个manager绑定了点击事件,之前的标记都无关联监听
  • pointAnnotation和viewAnnotation是单个变量,每次循环会被覆盖,无法存储所有标记对应的注解视图
  • 点击事件直接操作单个viewAnnotation,无法区分点击的是哪个标记

修复方案

  1. 只创建一个PointAnnotationManager,所有标记通过该manager统一管理
  2. 用集合存储每个PointAnnotation对应的ViewAnnotation,点击时精准匹配对应视图
  3. 调整点击事件逻辑,根据点击的标记找到对应的注解视图进行显示/隐藏控制

修改后的完整代码

先在类中声明集合变量

// 存储标记与对应注解视图的映射关系
private val annotationViewMap = mutableMapOf<PointAnnotation, View>()
private lateinit var pointAnnotationManager: PointAnnotationManager

修改地图加载代码

viewAnnotationManager = binding.mapView.viewAnnotationManager
binding.mapView.getMapboxMap().loadStyleUri(Style.MAPBOX_STREETS) {
    addAnnotationToMap()

    // 给唯一的manager绑定点击监听
    pointAnnotationManager.addClickListener { clickedAnnotation ->
        // 找到当前点击标记对应的注解视图
        val targetView = annotationViewMap[clickedAnnotation]
        targetView?.toggleViewVisibility()
        
        // 可选:自动隐藏其他已显示的注解视图
        annotationViewMap.forEach { (annotation, view) ->
            if (annotation != clickedAnnotation && view.visibility == View.VISIBLE) {
                view.visibility = View.GONE
            }
        }
        true
    }
}

修改标记加载代码

private fun addAnnotationToMap() {
    createListShop()
    val annotationApi = binding.mapView.annotations
    // 仅创建一次PointAnnotationManager
    pointAnnotationManager = annotationApi.createPointAnnotationManager()
    
    for (i in 0 until orders!!.shippingData.pickupPoints.size) {
        val nameShop = orders!!.shippingData.pickupPoints[i].friendlyName
        val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
            .withPoint(Point.fromLngLat(longitudelist[i], latitudeList[i]))
            .withIconImage(AppCompatResources.getDrawable(requireContext(), R.drawable.marker_location)!!.toBitmap())
        
        // 通过统一的manager创建标记
        val pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
        // 创建并存储对应的注解视图
        val viewAnnotation = prepareViewAnnotation(longitudelist[i], latitudeList[i], nameShop)
        annotationViewMap[pointAnnotation] = viewAnnotation
    }
}

private fun View.toggleViewVisibility() {
    visibility = if (visibility == View.VISIBLE) View.GONE else View.VISIBLE
}

// 修改方法,返回创建的注解视图用于存储
private fun prepareViewAnnotation(longitude: Double, latitude: Double, nameShop: String): View {
    val viewAnnotation = viewAnnotationManager.addViewAnnotation(
        resId = R.layout.view_marker,
        options = viewAnnotationOptions {
            geometry(fromLngLat(longitude, latitude))
            anchor(ViewAnnotationAnchor.BOTTOM)
            offsetY((pointAnnotation.iconImageBitmap?.height!!).toInt())
        }
    )

    ViewMarkerBinding.bind(viewAnnotation).apply {
        tvAnnotationMarker.text = nameShop
        // 默认隐藏注解视图,点击后再显示
        root.visibility = View.GONE
    }
    return viewAnnotation
}

关键说明

  • 单个PointAnnotationManager可统一管理所有标记,避免重复创建导致的监听丢失
  • annotationViewMap建立标记与视图的绑定关系,确保点击时能精准定位到对应注解
  • 可选的多视图互斥逻辑,能避免多个注解视图同时显示造成的界面混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:27:35