web-dev-qa-db-ja.com

GoogleマップのクラスターマーカーAndroid v2

GoogleマップからGoogleMapに異なるマーカーを配置する必要がありますAndroid v2 API。問題は、複数のマーカーが同じ位置(lat/lng)に設定されているため、ユーザーには「最新」のマーカー。

(ズームレベルに関して)同じエリアから異なるマーカーをクラスター化する可能性(最良の場合:ライブラリー)はありますか?

MarkerClustererについてはすでに読みましたが、これはJavaScript API用に設計されています。

15
Greeny

Googleは、Googleマップの一部としてこれを行うユーティリティを提供していますAndroid APIユーティリティライブラリ:

https://developers.google.com/maps/documentation/Android/utility/marker-clustering

ソースは次のとおりです。

https://github.com/googlemaps/Android-maps-utils

23
Intrications

私はこれをまだ試す機会がありませんでしたが、非常に有望に見えます。

http://code.google.com/p/Android-maps-extensions/

から この投稿

これは、かなりクールなクラスターアニメーションを含む別のライブラリです。

https://github.com/twotoasters/clusterkraf

20
DiscDev

少し遅れましたが、Clusterkrafは素晴らしいライブラリです。ぜひチェックしてください。

https://github.com/twotoasters/clusterkraf

7
Androiderson

独自のクラスタリングコードの実装を検討している他のユーザー向け。私のクラスタリングアルゴリズムを非常に高速にチェックして、驚くほどうまくいきます。

さまざまなライブラリを調べたところ、複雑すぎてWordを理解できないため、独自のクラスタリングアルゴリズムを作成することにしました。これがJavaのコードです。

    static int OFFSET = 268435456;
        static double RADIUS = 85445659.4471;
        static double pi = 3.1444;

    public static double lonToX(double lon) {
        return Math.round(OFFSET + RADIUS * lon * pi / 180);
    }

    public static double latToY(double lat) {
        return Math.round(OFFSET
                - RADIUS
                * Math.log((1 + Math.sin(lat * pi / 180))
                        / (1 - Math.sin(lat * pi / 180))) / 2);
    }

    public static int pixelDistance(double lat1, double lon1, double lat2,
            double lon2, int zoom) {
        double x1 = lonToX(lon1);
        double y1 = latToY(lat1);

        double x2 = lonToX(lon2);
        double y2 = latToY(lat2);

        return (int) (Math
                .sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2))) >> (21 - zoom);
    }

    static ArrayList<Cluster> cluster(ArrayList<Marker> markers, int zoom) {

        ArrayList<Cluster> clusterList = new ArrayList<Cluster>();

        ArrayList<Marker> originalListCopy = new ArrayList<Marker>();

        for (Marker marker : markers) {
            originalListCopy.add(marker);
        }

        /* Loop until all markers have been compared. */
        for (int i = 0; i < originalListCopy.size();) {

            /* Compare against all markers which are left. */

            ArrayList<Marker> markerList = new ArrayList<Marker>();
            for (int j = i + 1; j < markers.size();) {
                int pixelDistance = pixelDistance(markers.get(i).getLatitude(),
                        markers.get(i).getLongitude(), markers.get(j)
                                .getLatitude(), markers.get(j).getLongitude(),
                        zoom);

                if (pixelDistance < 40) {


                    markerList.add(markers.get(j));

                    markers.remove(j);

                    originalListCopy.remove(j);
                    j = i + 1;
                } else {
                    j++;
                }

            }

            if (markerList.size() > 0) {
 markerList.add(markers.get(i));                
Cluster cluster = new Cluster(clusterList.size(), markerList,
                        markerList.size() + 1, originalListCopy.get(i)
                                .getLatitude(), originalListCopy.get(i)
                                .getLongitude());
                clusterList.add(cluster);
                originalListCopy.remove(i);
                markers.remove(i);
                i = 0;

            } else {
                i++;
            }

            /* If a marker has been added to cluster, add also the one */
            /* we were comparing to and remove the original from array. */

        }
        return clusterList;
    }

Just pass in your array list here containing latitude and longitude then to display clusters. Here goes the function.


    @Override
    public void onTaskCompleted(ArrayList<FlatDetails> flatDetailsList) {

        LatLngBounds.Builder builder = new LatLngBounds.Builder();

        originalListCopy = new ArrayList<FlatDetails>();
        ArrayList<Marker> markersList = new ArrayList<Marker>();
        for (FlatDetails detailList : flatDetailsList) {

            markersList.add(new Marker(detailList.getLatitude(), detailList
                    .getLongitude(), detailList.getApartmentTypeString()));

            originalListCopy.add(detailList);

            builder.include(new LatLng(detailList.getLatitude(), detailList
                    .getLongitude()));

        }

        LatLngBounds bounds = builder.build();
        int padding = 0; // offset from edges of the map in pixels
        CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);

        googleMap.moveCamera(cu);

        ArrayList<Cluster> clusterList = Utils.cluster(markersList,
                (int) googleMap.getCameraPosition().zoom);

        // Removes all markers, overlays, and polylines from the map.
        googleMap.clear();

        // Zoom in, animating the camera.
        googleMap.animateCamera(CameraUpdateFactory.zoomTo(previousZoomLevel),
                2000, null);

        CircleOptions circleOptions = new CircleOptions().center(point) //
                // setcenter
                .radius(3000) // set radius in meters
                .fillColor(Color.TRANSPARENT) // default
                .strokeColor(Color.BLUE).strokeWidth(5);

        googleMap.addCircle(circleOptions);

        for (Marker detail : markersList) {

            if (detail.getBhkTypeString().equalsIgnoreCase("1 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk1)));
            } else if (detail.getBhkTypeString().equalsIgnoreCase("2 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk_2)));

            }

            else if (detail.getBhkTypeString().equalsIgnoreCase("3 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk_3)));

            } else if (detail.getBhkTypeString().equalsIgnoreCase("2.5 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk2)));

            } else if (detail.getBhkTypeString().equalsIgnoreCase("4 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk_4)));

            } else if (detail.getBhkTypeString().equalsIgnoreCase("5 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk5)));

            } else if (detail.getBhkTypeString().equalsIgnoreCase("5+ BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk_5)));

            }

            else if (detail.getBhkTypeString().equalsIgnoreCase("2 BHK")) {
                googleMap.addMarker(new MarkerOptions()
                        .position(
                                new LatLng(detail.getLatitude(), detail
                                        .getLongitude()))
                        .snippet(String.valueOf(""))
                        .title("Flat" + flatDetailsList.indexOf(detail))
                        .icon(BitmapDescriptorFactory
                                .fromResource(R.drawable.bhk_2)));

            }
        }

        for (Cluster cluster : clusterList) {

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inMutable = true;
            options.inPurgeable = true;
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                    R.drawable.cluster_marker, options);

            Canvas canvas = new Canvas(bitmap);

            Paint paint = new Paint();
            Paint.setColor(getResources().getColor(R.color.white));
            Paint.setTextSize(30);

            canvas.drawText(String.valueOf(cluster.getMarkerList().size()), 10,
                    40, Paint);

            googleMap.addMarker(new MarkerOptions()
                    .position(
                            new LatLng(cluster.getClusterLatitude(), cluster
                                    .getClusterLongitude()))
                    .snippet(String.valueOf(cluster.getMarkerList().size()))
                    .title("Cluster")
                    .icon(BitmapDescriptorFactory.fromBitmap(bitmap)));

        }

    }
6
user1530779

次の手順を実行する必要があります。

  1. /を実装する必要があります Google Maps Android APIユーティリティライブラリ

Androidスタジオ/ Gradle:

_dependencies {
    compile 'com.google.maps.Android:android-maps-utils:0.3+'
}
_
  1. 次に、Googleの公式ドキュメントを読む必要があります-> Google Maps Android Marker Clustering Utility

簡単なマーカークラスタラーを追加します

以下の手順に従って、10個のマーカーの単純なクラスターを作成します。結果は次のようになりますが、表示/クラスター化されるマーカーの数はズームレベルに応じて変化します。

Add a simple marker clusterer

必要な手順の概要は次のとおりです。

  1. マップ上のマーカーを表すClusterItemを実装します。クラスター項目は、マーカーの位置をLatLngオブジェクトとして返します。
  2. 新しいClusterManagerを追加して、ズームレベルに基づいてクラスターアイテム(マーカー)をグループ化します。
  3. ClusterManagerはリスナーを実装するため、マップのOnCameraChangeListener()ClusterManagerに設定します。
  4. マーカークリックイベントに応答して特定の機能を追加する場合は、ClusterManagerがリスナーを実装するため、マップのOnMarkerClickListener()ClusterManagerに設定します。
  5. マーカーをClusterManagerにフィードします。

手順をさらに詳しく見てみましょう。10個のマーカーの単純なクラスターを作成するには、最初にMyItemを実装するClusterItemクラスを作成します。

_public class MyItem implements ClusterItem {
    private final LatLng mPosition;

    public MyItem(double lat, double lng) {
        mPosition = new LatLng(lat, lng);
    }

    @Override
    public LatLng getPosition() {
        return mPosition;
    }
}
_

マップアクティビティにClusterManagerを追加し、クラスターアイテムにフィードします。 ClusterManagerがMyItem型であることを宣言する型引数_<MyItem>_に注意してください。

_private void setUpClusterer() {
    // Declare a variable for the cluster manager.
    private ClusterManager<MyItem> mClusterManager;

    // Position the map.
    getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));

    // Initialize the manager with the context and the map.
    // (Activity extends context, so we can pass 'this' in the constructor.)
    mClusterManager = new ClusterManager<MyItem>(this, getMap());

    // Point the map's listeners at the listeners implemented by the cluster
    // manager.
    getMap().setOnCameraChangeListener(mClusterManager);
    getMap().setOnMarkerClickListener(mClusterManager);

    // Add cluster items (markers) to the cluster manager.
    addItems();
}

private void addItems() {

    // Set some lat/lng coordinates to start with.
    double lat = 51.5145160;
    double lng = -0.1270060;

    // Add ten cluster items in close proximity, for purposes of this example.
    for (int i = 0; i < 10; i++) {
        double offset = i / 60d;
        lat = lat + offset;
        lng = lng + offset;
        MyItem offsetItem = new MyItem(lat, lng);
        mClusterManager.addItem(offsetItem);
    }
}
_

デモ

https://www.youtube.com/watch?v=5ZnVraO1mT4

Github

詳細情報/完成したプロジェクトが必要な場合は、以下にアクセスしてください https://github.com/dimitardanailov/googlemapsclustermarkers

他にご不明な点がございましたら、お気軽にお問い合わせください。

5
d.danailov

Clusterkrafで問題が発生している方(動作させることができません!)および使用できない方Android-maps-extensionPlay Services libのカスタムビルドが同梱されているため、この他のライブラリを提案したいと思います。これは小さく、よく記述されており、箱から出して動作します。

Clustererhttps://github.com/mrmans0n/clusterer

他の2つのライブラリを使用するために丸一日過ごした後、これは私の日を救いました!

4
lorenzo-s

最新のマーカーのみを取得している場合は、すべてのマーカーをクラスター化する必要があります

> private ClusterManager<MyItem> mClusterManager;

アイテムを追加した後

mClusterManager.addItem("your item");
mClusterManager.cluster();
2
Mohammad

Googleマップのパフォーマンスに問題がある方のために、Android APIユーティリティライブラリ、専用の高速クラスタリングライブラリ https://github.comを作成しました。/sharewire/google-maps-clustering 。マップ上の20000マーカーを簡単に処理できます。

0
makovkastar