如何为Mapbox中所有标记添加点击事件并显示对应地址?
解决Mapbox多标记点击事件仅单个生效的问题
问题根源
你的代码存在三个核心问题:
- 循环中每次创建新的
PointAnnotationManager,导致只有最后一个manager绑定了点击事件,之前的标记都无关联监听 pointAnnotation和viewAnnotation是单个变量,每次循环会被覆盖,无法存储所有标记对应的注解视图- 点击事件直接操作单个
viewAnnotation,无法区分点击的是哪个标记
修复方案
- 只创建一个
PointAnnotationManager,所有标记通过该manager统一管理 - 用集合存储每个
PointAnnotation对应的ViewAnnotation,点击时精准匹配对应视图 - 调整点击事件逻辑,根据点击的标记找到对应的注解视图进行显示/隐藏控制
修改后的完整代码
先在类中声明集合变量
// 存储标记与对应注解视图的映射关系 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
相关产品推荐
相关产品推荐

