如何使用android-maps-utils更改点击的标记图标?

8
在我的Android项目中,我使用android-maps-utils库将聚类应用于地图视图上的一堆标记。每当单击一个标记时,我会通过onClusterItemClick得到通知,以便我可以执行一些操作。
public interface OnClusterItemClickListener<T extends ClusterItem> {
    public boolean onClusterItemClick(T item);
}

现在,我想让用户知道哪个标记被点击了。最简单的视觉反馈是改变(标记图标的)颜色。可以通过MarkerOptions对象设置图标,该对象可以在onBeforeClusterItemRendered(T item, MarkerOptions markerOptions)中访问,如下所示:
markerOptions.icon(
    BitmapDescriptorFactory.defaultMarker(
        BitmapDescriptorFactory.HUE_YELLOW));

如果我可以访问Marker对象本身,例如在onMarkerClick(Marker marker)中,我可以通过setIcon更改图标。

如何更改已点击标记的图标?


相关

3个回答

15

我注意到DefaultClusterRenderer提供了一些方法来检索与ClusterItem相关联的Marker对象。由于我已经使用自定义渲染器,因此我能够像这样访问所需的Marker对象:

mSelectedMarker = mCustomClusterItemRenderer.getMarker(mSelectedClusterItem);

这使我能够在 onClusterItemClick() 中更改图标:

private void updateSelectedMarker() {
    if (mSelectedMarker != null) {
        mSelectedMarker.setIcon(
                BitmapDescriptorFactory.defaultMarker(
                        BitmapDescriptorFactory.HUE_YELLOW));
    }
}

1
谢谢,你是如何在点击其他项目后撤销更新的? - KasparTr
这是一段时间以前的事了。我认为您需要在之前重置所选标记,或者只需迭代所有标记。 - JJD
为了避免对标记进行迭代,我记住了上次选择的标记,并在更新下一个标记之前撤销了对上一个标记的更改。谢谢。 - KasparTr
我刚刚做了这个,但图标没有改变。你们是不是调用了mClusterManager.cluster()? - terencey
@KasparTr,你是如何记住上次选择的标记的? - NizarETH

4
感谢@JJD的帮助,我用Kotlin写了相同的代码。
private var selectedBitmap: BitmapDescriptor? = null
private var unselectedBitmap: BitmapDescriptor? = null
private var lastMarker: Marker? = null
private var clusterManager: ClusterManager<StationClusterItem>? = null

override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap

    clusterManager = ClusterManager(context!!, googleMap)
    val clusterRenderer = MarkerClusterRenderer(context!!, googleMap, clusterManager!!,
        unselectedBitmap!!)
    clusterManager!!.renderer = clusterRenderer
    // Add your items to the ClusterManager here with clusterManager?.addItem().
    // Better is in background thread.
    val boundsBuilder = LatLngBounds.Builder()
    ...

    clusterManager!!.cluster()
    // Add this listener to make ClusterManager correctly zoom clusters and markers.
    googleMap.setOnCameraIdleListener(clusterManager)

    // This method is needed to use setOnClusterItemClickListener.
    googleMap.setOnMarkerClickListener(clusterManager)
    clusterManager!!.setOnClusterItemClickListener { item ->
        lastMarker?.setIcon(unselectedBitmap)
        lastMarker = clusterRenderer.getMarker(item) // Here we access a selected marker.
        lastMarker?.setIcon(selectedBitmap)
        // false - to show info window. See GoogleMap.InfoWindowAdapter.
        // true - to hide info window.
        false
    }
}

class MarkerClusterRenderer(
    val context: Context,
    val map: GoogleMap,
    clusterManager: ClusterManager<StationClusterItem>,
    private val markerBitmap: BitmapDescriptor
) : DefaultClusterRenderer<StationClusterItem>(context, map, clusterManager) {

    init {
        minClusterSize = 1 // 2, 3 or more, as you wish.
    }    

    override fun onBeforeClusterItemRendered(item: StationClusterItem?,
                                             markerOptions: MarkerOptions?) {
        super.onBeforeClusterItemRendered(item, markerOptions)
        markerOptions?.icon(markerBitmap)
    }
}

更新

当点击标记时(在一行代码lastMarker?.setIcon(unselectedBitmap)中),我收到了一个异常:java.lang.IllegalArgumentException: Unmanaged descriptor

在研究了IllegalArgumentException: Unmanaged descriptor using gms.maps.model.Marker.setIcon之后,我重写了该侦听器:

private var selectedItem: StationClusterItem? = null

    clusterManager!!.setOnClusterItemClickListener { item ->
        if (selectedItem != null) {
            // Set here a reference to a previous marker.
            // We save a reference to a previous item, not to a marker.
            val lastMarker = clusterRenderer.getMarker(selectedItem)
            lastMarker?.setIcon(unselectedBitmap)
        }
        selectedItem = item
        // Now get a reference to a selected marker.
        val newMarker = clusterRenderer.getMarker(item)
        newMarker?.setIcon(selectedBitmap)
        false
    }

感谢您注意到 IllegalArgumentException - Vlad
@Vlad,谢谢!我也明白了,在setOnClusterItemClickListener中的false会影响信息窗口,请参见https://dev59.com/-mMm5IYBdhLWcg3wIsXj#60833015。 - CoolMind

1
如果标记由于某种原因(没有选中任何标记)在程序上被取消选择,则先前的答案对我不起作用。
我将此代码添加到DefaultClusterRenderer继承者中。
init {
    viewModel.selectedItem.observeForever {
        if (it == null) {
            clusterManager.cluster()
        }
    }
}

在此渲染器生命周期结束后,请不要忘记销毁它。实际上,在渲染器之外使用更好。我在我的Activity中使用它。

private fun onMapClickListener(){
    if (viewModel.selectedItem.value != null) clusterManager.cluster()
}

默认图标更改代码(这里只是切换图标颜色):

override fun onBeforeClusterItemRendered(item: ClusterMarker, markerOptions: MarkerOptions) {
    markerOptions.icon(getMarkerColor(item))
}

override fun onClusterItemUpdated(item: ClusterMarker, marker: Marker) {
    marker.setIcon(getMarkerColor(item))
}

private fun getMarkerColor(item: ClusterMarker): BitmapDescriptor {
    val color = if (item.id == viewModel.selectedItem.value?.id) BitmapDescriptorFactory.HUE_ORANGE
    else item.getColor()
    return BitmapDescriptorFactory.defaultMarker(color)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接