web-dev-qa-db-ja.com

Androidクラスターとマーカーのクリック

マップ上でAndroidクラスタリングユーティリティを使用しており、クラスタリングライブラリによって処理されるすべてのマーカーに対してmClusterManager.setOnClusterItemClickListener()を使用してonclickリスナーを正常に実装しました。

また、一部のマーカーを常に非クラスター化する必要があるため、mClusterManagerを使用せずに、マップのmMap.addMarker()を直接使用して、いくつかのマーカーを追加します。これにより、マーカーがマップ上でクラスター化されることはありません。

私の問題は、クリックされたクラスターのマーカーを処理するためにすでにmMap.setOnMarkerClickListener(mClusterManager)を使用しているため、これらのマーカー(常にクラスター化されていないマーカー)のクリックをインターセプトできないことです。

クリックされたクラスター化されたマーカーと、クラスター化ライブラリによって処理されていないクリックされたマーカーをリッスンする方法はありますか?

または、一部のマーカーをクラスター化しないようにクラスターマネージャーを指定する方法はありますか?この場合、すべてのマーカーがクラスタリングユーティリティを使用して表示されるため、これらの異なるクリックリスナーを処理する必要はありません。

ありがとうございました

12
tio oit

MarkerManagerコンストラクターに渡す新しいClusterManagerを作成できます。次に、_MarkerManager#newCollection_を使用して新しいマーカーコレクションを作成し、_MarkerManager.Collection#addMarker_メソッドを使用して通常のマーカーをマップに追加します。

次に、mMap.setOnMarkerClickListener(mClusterManager)を呼び出す代わりに、mMap.setOnMarkerClickListener(mMarkerManager)を呼び出すと、Markerクリックイベントの適切なリスナーへの転送が処理されます。また、MarkerManager.Collection#setOnMarkerClickListener(GoogleMap.OnMarkerClickListener markerClickListener)関数を使用して、通常のマーカー用にonMarkerClickリスナーを設定する必要があります。

MarkerManager および ClusterManager クラスのソースを調べて、クラスがどのように相互作用するかをよりよく理解することをお勧めします。

16
NasaGeek

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;
}
8
Atul O Holic

簡単な解決策

同じ問題が発生しました。解決策は簡単です。独自のイベントリスナーから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
Alex Gata

ここに私のコードがあります。この例は、必要なものがすべて揃っています。

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;
    }


 }
0
Zhar