【问题标题】:How to change the clicked marker icon using android-maps-utils?如何使用 android-maps-utils 更改单击的标记图标?
【发布时间】:2015-08-30 20:17:55
【问题描述】:

在我的 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 更改图标。

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


相关

【问题讨论】:

    标签: android google-maps-markers android-maps-utils


    【解决方案1】:

    我注意到DefaultClusterRenderer 提供了检索与ClusterItem 关联的Marker 对象的方法。因为无论如何我都使用自定义渲染器,所以我能够访问所需的 Marker 对象,如下所示:

    mSelectedMarker = mCustomClusterItemRenderer.getMarker(mSelectedClusterItem);
    

    这让我可以更改onClusterItemClick() 中的图标:

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

    【讨论】:

    • 谢谢,点击其他项目后如何撤消更新?
    • 不久前。我认为您需要在之前重置以前选择的标记或只迭代所有标记。
    • 为了避免重复标记,我记住了最后一个选择的标记,并在更新下一个标记之前撤消了对最后一个标记的更改。谢谢
    • 我只是这样做了,但图标没有改变。你们打电话给 mClusterManager.cluster() 吗?
    • @KasparTr 你是怎么记住最后选择的标记的?
    【解决方案2】:

    感谢@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)
        }
    }
    

    更新

    我遇到了一个异常:java.lang.IllegalArgumentException: Unmanaged descriptor 单击标记时(在一行 lastMarker?.setIcon(unselectedBitmap) 中)。

    研究完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,谢谢!我也明白,setOnClusterItemClickListener 中的false 会影响信息窗口,请参阅stackoverflow.com/a/60833015/2914140
    【解决方案3】:

    如果标记由于随机原因以编程方式未被选中(未选中),则之前的答案对我来说无法正常工作。

    我将此代码添加到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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      • 2013-08-31
      • 2015-09-07
      • 1970-01-01
      • 2014-11-29
      • 2016-12-25
      • 1970-01-01
      相关资源
      最近更新 更多