安卓集群和标记点击

12

我在地图上使用 Android 聚类工具,并成功地使用 mClusterManager.setOnClusterItemClickListener() 为聚类库处理的所有标记实现了 onclick 监听器。

因为我还希望一些标记始终未被聚集,所以我也使用 mMap.addMarker() 直接添加了一些标记,这样我就确定它们永远不会在地图上聚集。

我的问题是,我不能拦截那些标记(始终未聚类的标记)上的点击事件,因为我已经使用了 mMap.setOnMarkerClickListener(mClusterManager) 来处理点击的聚类标记。

有没有办法监听已聚类标记和聚类库没有处理的标记的点击事件?

或者是否有一种方式可以指定聚类管理器永不聚集某些标记?在这种情况下,由于所有标记都将使用聚类工具显示,因此我将不必处理这些不同的点击监听器。

谢谢

4个回答

20
您可以创建一个新的MarkerManager并将其传递给ClusterManager构造函数。然后,使用MarkerManager#newCollection创建一个新的标记集合,并使用MarkerManager.Collection#addMarker方法将常规标记添加到地图上。
然后,不要调用mMap.setOnMarkerClickListener(mClusterManager),而是调用mMap.setOnMarkerClickListener(mMarkerManager),它将处理将您的标记单击事件转发到正确的侦听器。您还需要使用MarkerManager.Collection#setOnMarkerClickListener(GoogleMap.OnMarkerClickListener markerClickListener)函数为普通标记设置onMarkerClick监听器。
建议查看MarkerManagerClusterManager类的源代码,以更好地了解这些类之间的交互。

3
完美,它正在工作,谢谢。 阅读您提供的MarkerManager链接真的对我很有帮助,这是一个很好的推荐。 - tio oit
@NasaGeek 在使用 MarkerManager 添加标记后,聚类功能无法正常工作!您能提供一些代码片段吗? - Maddy

8

另一种接收 Marker click 事件的方法是使用 OnClusterItemClickListener 接口。

调用 mClusterManager.setOnClusterItemClickListener(this); 并使您的类实现 OnClusterItemClickListener

然后在 onClusterItemClick 方法中,您将获得被点击的标记,它是 ClusterItem

@Override
public boolean onClusterItemClick(ClusterItem clusterItem) {

    Toast.makeText(getActivity(), "Latitude " + clusterItem.getPosition().latitude, Toast.LENGTH_LONG).show();

    return true;
}

1
这更简单。 - 最白目
1
但是如果您有一个从ClusterItem扩展的类,它就没有进一步的属性。例如IconId等。 - Dr.jacky
@Mr.Hyde也许你可以欺骗系统,如果你有一个数据库,Lat和Lng不会改变,你可以反向数据。我会在我的项目中实现这个。谢谢@Atul! - Federico Navarrete
@Mr.Hyde 传递到 onClusterItemClick 方法中的项目应该仍然保留其原始类型,这样您就可以将其强制转换为正确的对象以保留字段。例如:MyObject mine = (MyObject) clusterItem; - Zurvæ

0

简单解决方案

我遇到了同样的问题。解决方案很简单:从你自己的事件监听器中调用ClusterManager监听器。看一下这个概念:

private OnMapReadyCallback listenerMapReady = (googleMap) ->
{
    googleMap.setOnCameraIdleListener(() -> {
        mClusterManager.onCameraIdle(); //call cluster manager listener
        //....your code for setOnCameraIdleListener event
    });

    googleMap.setOnMarkerClickListener(marker -> {
        if (marker != null && ... check if marker is NOT from cluster manager ....) {
            //......your code for unclustered markers, added directly to the map
            return false;
        }
        else
            return mClusterManager != null && mClusterManager.onMarkerClick(marker); // let cluster manager do his job
    });
}

为确保集群管理器内部不会拦截 onMarkerClick 监听器,让我们在集群管理器完成操作后每次重置监听器。我已经将其放入 OnCameraIdle 事件中:
public class FragmentRoutes extends Fragment {

private MapView mMapView;
private GoogleMap mMap;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_routes, container, false);

    mMapView = rootView.findViewById(R.id.ac_main_map); // map rendering holder
    if (mMapView != null)
        mMapView.onCreate(savedInstanceState);
    //....... other onCreate mess
}


@Override
public void onResume() {
    super.onResume();
    if (mMapView != null) {
        mMapView.onResume();
        mMapView.getMapAsync(listenerMapReady);
    }
}


// on marker click listener for the map
private GoogleMap.OnMarkerClickListener listenerMarkerClick = marker -> {
    //markers which tag is TransportItem were added directly to map, I will take care of them
    if (marker != null && marker.getTag() instanceof TransportItem) {
        //......do my tasks for clicked transport marker
        return false;
    }
    else {
       // other markers are cluster manager markers, process as usual
       return mClusterManager != null && mClusterManager.onMarkerClick(marker);
    }
}

// listener for map ready event
private OnMapReadyCallback listenerMapReady = (googleMap) ->
{
    if (getContext() == null)
        return;

    mMap = googleMap;

    mMap.setOnCameraIdleListener(() -> {
        mClusterManager.onCameraIdle();

        //....your code for setOnCameraIdleListener event

        // now reset marker click listener
        mMap.setOnMarkerClickListener(listenerMarkerClick); //reset marker click listener
    });
}


}

就这些了!祝你愉快的安卓编程 :)


0

这里可以看到我的代码。示例已经包括了你所需要的一切。

public class HomeFragment extends Fragment implements OnMapReadyCallback, ClusterManager.OnClusterClickListener<MarkerClusterItem> {

    ...

    @Override
    public void onMapReady(GoogleMap googleMap) {
        // Add a marker in Sydney, Australia,
        this.googleMap = googleMap;
        this.googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);


        setUpClusterManager();

        ...
    }

    private void setUpClusterManager(){
        // cluster
        clusterManager = new ClusterManager<MarkerClusterItem>(getActivity(), this.googleMap);
        clusterManager.setAnimation(false);
        MarkerClusterRenderer clusterRenderer = new MarkerClusterRenderer(getActivity(), googleMap, clusterManager);
        clusterManager.setRenderer(clusterRenderer);
        // marker clic
        clusterManager.setOnClusterClickListener(this);
    }

    @Override
    public boolean onClusterClick(Cluster<MarkerClusterItem> cluster) {
    if (cluster == null) return false;
        // do your stuff here 
        return true;
    }


 }

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