マップ上で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 および ClusterManager クラスのソースを調べて、クラスがどのように相互作用するかをよりよく理解することをお勧めします。
Marker
のクリックイベントを受信するもう1つの方法は、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;
}
同じ問題が発生しました。解決策は簡単です。独自のイベントリスナーから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
});
}
}
それで全部です!幸せなアンドロイド:)
ここに私のコードがあります。この例は、必要なものがすべて揃っています。
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;
}
}