Android 集群和标记点击次数
Android cluster and marker clicks
我在地图上使用 android 聚类实用程序,并成功地为聚类库处理的所有标记实现了带有 mClusterManager.setOnClusterItemClickListener() 的 onclick 侦听器。
因为我也希望一些标记始终不聚类,所以我还添加了一些标记而不使用 mClusterManager 而是直接使用地图的 mMap.addMarker(),这样我可以确保它们永远不会聚类地图。
我的问题是我无法拦截对这些标记(总是非聚类标记)的点击,因为我已经使用 mMap.setOnMarkerClickListener(mClusterManager) 来处理点击的聚类标记。
有没有办法监听点击的聚类标记和未被聚类库处理的点击标记?
或者有没有办法指定集群管理器从不对某些标记进行集群?在这种情况下,我不必处理那些不同的点击侦听器,因为所有标记都将使用聚类实用程序显示。
谢谢
您可以创建一个新的 MarkerManager
并将其传递给 ClusterManager
构造函数。然后使用 MarkerManager#newCollection
创建一个新的标记集合,并使用 MarkerManager.Collection#addMarker
方法将普通标记添加到地图。
然后,不调用 mMap.setOnMarkerClickListener(mClusterManager)
,而是调用 mMap.setOnMarkerClickListener(mMarkerManager)
,它将处理将您的 Marker
单击事件转发给适当的侦听器。您还需要使用 MarkerManager.Collection#setOnMarkerClickListener(GoogleMap.OnMarkerClickListener markerClickListener)
函数为普通标记设置 onMarkerClick 侦听器。
我建议查看 MarkerManager and ClusterManager 类 的源代码以更好地了解 类 是如何交互的。
另一种接收 Marker
的点击事件的方法是使用 OnClusterItemClickListener
界面。
调用 mClusterManager.setOnClusterItemClickListener(this);
并让你的 class 实现 OnClusterItemClickListener
然后在 onClusterItemClick
方法中,您将获得 ClusterItem,它是被点击的标记,
@Override
public boolean onClusterItemClick(ClusterItem clusterItem) {
Toast.makeText(getActivity(), "Latitude " + clusterItem.getPosition().latitude, Toast.LENGTH_LONG).show();
return true;
}
在这里你可以看到我的代码。该示例包含您需要的所有内容。
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;
}
}
简单的解决方案
刚遇到同样的问题。解决方案很简单:从您自己的事件侦听器调用 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
});
}
}
就是这样!快乐的机器人:)
我在地图上使用 android 聚类实用程序,并成功地为聚类库处理的所有标记实现了带有 mClusterManager.setOnClusterItemClickListener() 的 onclick 侦听器。
因为我也希望一些标记始终不聚类,所以我还添加了一些标记而不使用 mClusterManager 而是直接使用地图的 mMap.addMarker(),这样我可以确保它们永远不会聚类地图。
我的问题是我无法拦截对这些标记(总是非聚类标记)的点击,因为我已经使用 mMap.setOnMarkerClickListener(mClusterManager) 来处理点击的聚类标记。
有没有办法监听点击的聚类标记和未被聚类库处理的点击标记?
或者有没有办法指定集群管理器从不对某些标记进行集群?在这种情况下,我不必处理那些不同的点击侦听器,因为所有标记都将使用聚类实用程序显示。
谢谢
您可以创建一个新的 MarkerManager
并将其传递给 ClusterManager
构造函数。然后使用 MarkerManager#newCollection
创建一个新的标记集合,并使用 MarkerManager.Collection#addMarker
方法将普通标记添加到地图。
然后,不调用 mMap.setOnMarkerClickListener(mClusterManager)
,而是调用 mMap.setOnMarkerClickListener(mMarkerManager)
,它将处理将您的 Marker
单击事件转发给适当的侦听器。您还需要使用 MarkerManager.Collection#setOnMarkerClickListener(GoogleMap.OnMarkerClickListener markerClickListener)
函数为普通标记设置 onMarkerClick 侦听器。
我建议查看 MarkerManager and ClusterManager 类 的源代码以更好地了解 类 是如何交互的。
另一种接收 Marker
的点击事件的方法是使用 OnClusterItemClickListener
界面。
调用 mClusterManager.setOnClusterItemClickListener(this);
并让你的 class 实现 OnClusterItemClickListener
然后在 onClusterItemClick
方法中,您将获得 ClusterItem,它是被点击的标记,
@Override
public boolean onClusterItemClick(ClusterItem clusterItem) {
Toast.makeText(getActivity(), "Latitude " + clusterItem.getPosition().latitude, Toast.LENGTH_LONG).show();
return true;
}
在这里你可以看到我的代码。该示例包含您需要的所有内容。
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;
}
}
简单的解决方案
刚遇到同样的问题。解决方案很简单:从您自己的事件侦听器调用 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
});
}
}
就是这样!快乐的机器人:)