【androidjava】MarkerClustererカスタマイズする方法

クラスターを自分好みにしたい時は、osmbonuspackで提供されているMarkerClustererを継承した

サブクラスを使うことでクラスターの画像をカスタマイズすることができます。

必要なもの
変数:ズームレベル、クラスターに表示するテキスト、マーカー等


protected int mMaxClusteringZoomLevel = 17;
protected int mRadiusInPixels = 100;
protected double mRadiusInMeters;
protected Paint mTextPaint;
private ArrayList<Marker> mClonedMarkers;
/** cluster icon anchor */
public float mAnchorU = Marker.ANCHOR_CENTER, mAnchorV = Marker.ANCHOR_CENTER;
/** anchor point to draw the number of markers inside the cluster icon */
public float mTextAnchorU = Marker.ANCHOR_CENTER, mTextAnchorV = Marker.ANCHOR_CENTER;

コンストラクタ(値の初期値)

テキストに表示する基本データになります。osmdroidを使ったことがある人なら

すぐ分かるはずw

public CustomMarkerClusterer(Context ctx) {
        super();

        mTextPaint = new Paint();
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setTextSize(40.0f);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setAntiAlias(true);
    }

buildClusterMarkerメソッド

クラスターをカスタマイズためのポイントがこのメソッドです。

引数として取れるgetSize()から取得したマーカーの集まりが取得できるので

この数に応じてクラスターの種類を切り替えることができます。

osmbonuspackのgitにMarkerClustererの基本メソッドがあるので

最初はそれを丸ごとコピーして後にcluster.getSize()などを使って

臨機応変にクラスターを変更するというのが主な動きになります。

@Override
    public Marker buildClusterMarker(StaticCluster cluster, MapView mapView) {
Marker m = new Marker(mapView);
        m.setPosition(cluster.getPosition());
        m.setInfoWindow(null);
        m.setAnchor(mAnchorU, mAnchorV);
        Bitmap icon = null;
        if (cluster.getSize() &lt; 10 &amp;&amp; cluster.getSize() &gt;= 5) {
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.yellowmarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        } else if(cluster.getSize() &gt;= 10){
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.orangemarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        } else {
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.greenmarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        }
        Bitmap mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);
        Canvas iconCanvas = new Canvas(mutableBitmap);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * icon.getWidth(),
                mTextAnchorV * icon.getHeight() - textHeight / 2,
                mTextPaint);
        m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));

        return m;
}

全体のコードはこちら。


public class CustomMarkerClusterer extends MarkerClusterer {
    protected int mMaxClusteringZoomLevel = 17;
    protected int mRadiusInPixels = 100;
    protected double mRadiusInMeters;
    protected Paint mTextPaint;
    private ArrayList&lt;Marker&gt; mClonedMarkers;

    /** cluster icon anchor */
    public float mAnchorU = Marker.ANCHOR_CENTER, mAnchorV = Marker.ANCHOR_CENTER;
    /** anchor point to draw the number of markers inside the cluster icon */
    public float mTextAnchorU = Marker.ANCHOR_CENTER, mTextAnchorV = Marker.ANCHOR_CENTER;
    public CustomMarkerClusterer(Context ctx) {
        super();

        mTextPaint = new Paint();
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setTextSize(40.0f);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setAntiAlias(true);
    }
    /** If you want to change the default text paint (color, size, font) */
    public Paint getTextPaint(){
        return mTextPaint;
    }

    /** Set the radius of clustering in pixels. Default is 100px. */
    public void setRadius(int radius){
        mRadiusInPixels = radius;
    }

    /** Set max zoom level with clustering. When zoom is higher or equal to this level, clustering is disabled.
     * You can put a high value to disable this feature. */
    public void setMaxClusteringZoomLevel(int zoom){
        mMaxClusteringZoomLevel = zoom;
    }
    @Override
    public ArrayList&lt;StaticCluster&gt; clusterer(MapView mapView) {
        ArrayList&lt;StaticCluster&gt; clusters = new ArrayList&lt;StaticCluster&gt;();
        convertRadiusToMeters(mapView);

        mClonedMarkers = new ArrayList&lt;Marker&gt;(mItems); //shallow copy
        while (!mClonedMarkers.isEmpty()) {
            Marker m = mClonedMarkers.get(0);
            StaticCluster cluster = createCluster(m, mapView);
            clusters.add(cluster);
        }
        return clusters;
    }
    private StaticCluster createCluster(Marker m, MapView mapView) {
        GeoPoint clusterPosition = m.getPosition();

        StaticCluster cluster = new StaticCluster(clusterPosition);
        cluster.add(m);

        mClonedMarkers.remove(m);

        if (mapView.getZoomLevel() &gt; mMaxClusteringZoomLevel) {
            //above max level =&gt; block clustering:
            return cluster;
        }
        Iterator&lt;Marker&gt; it = mClonedMarkers.iterator();
        while (it.hasNext()) {
            Marker neighbour = it.next();
            int distance = (int) clusterPosition.distanceToAsDouble(neighbour.getPosition());
            if (distance &lt;= mRadiusInMeters) {
                cluster.add(neighbour);
                it.remove();
            }
        }
        return cluster;
    }
    @Override
    public Marker buildClusterMarker(StaticCluster cluster, MapView mapView) {
        Marker m = new Marker(mapView);
        m.setPosition(cluster.getPosition());
        m.setInfoWindow(null);
        m.setAnchor(mAnchorU, mAnchorV);
        Bitmap icon = null;
        if (cluster.getSize() &lt; 10 &amp;&amp; cluster.getSize() &gt;= 5) {
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.yellowmarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        } else if(cluster.getSize() &gt;= 10){
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.orangemarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        } else {
            Drawable clusterIconD = mapView.getContext().getResources().getDrawable(R.drawable.greenmarker);
            icon = ((BitmapDrawable) clusterIconD).getBitmap();
        }
        Bitmap mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);
        Canvas iconCanvas = new Canvas(mutableBitmap);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * icon.getWidth(),
                mTextAnchorV * icon.getHeight() - textHeight / 2,
                mTextPaint);
        m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));

        return m;
    }

    @Override
    public void renderer(ArrayList&lt;StaticCluster&gt; clusters, Canvas canvas, MapView mapView) {
        for (StaticCluster cluster : clusters) {
            if (cluster.getSize() == 1) {
                //cluster has only 1 marker =&gt; use it as it is:
                cluster.setMarker(cluster.getItem(0));
            } else {
                //only draw 1 Marker at Cluster center, displaying number of Markers contained
                Marker m = buildClusterMarker(cluster, mapView);
                cluster.setMarker(m);
            }
        }
    }
    private void convertRadiusToMeters(MapView mapView) {

        Rect mScreenRect = mapView.getIntrinsicScreenRect(null);

        int screenWidth = mScreenRect.right - mScreenRect.left;
        int screenHeight = mScreenRect.bottom - mScreenRect.top;

        BoundingBox bb = mapView.getBoundingBox();

        double diagonalInMeters = bb.getDiagonalLengthInMeters();
        double diagonalInPixels = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight);
        double metersInPixel = diagonalInMeters / diagonalInPixels;

        mRadiusInMeters = mRadiusInPixels * metersInPixel;
    }
}

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG