web-dev-qa-db-fra.com

Android mappe la couleur de l'icône du cluster des utilitaires

Existe-t-il une méthode pour modifier la couleur d'arrière-plan de l'élément de cluster? (celui qui affiche le nombre de marqueurs, comme 100+, 200+ ...). J'ai essayé de regarder le code source du ClusterManager mais je n'ai trouvé aucune option pour changer la couleur, mais peut-être que quelqu'un ici sait comment faire cela. Je veux essentiellement "matérialiser" un peu ces couleurs.

19
qwertz

J'ai pu obtenir une implémentation approximative en utilisant cette démo à partir des exemples de bibliothèque comme guide.

J'ai utilisé l'icône lens des icônes Material Design de ici . Après avoir téléchargé le lens Zip, je mets ic_lens_black_24dp.png Sous le dossier dessinable. Ensuite, j'ai utilisé la méthode Drawable.setColorFilter () pour changer la couleur par défaut dans le code.

J'ai également pu changer la couleur du marqueur par défaut, et j'ai pensé que je l'inclurais également ici.

Tout d'abord, définissez un Renderer en appelant setRenderer():

 mClusterManager.setRenderer(new MyClusterRenderer(this, mMap,
                mClusterManager));

Ensuite, définissez la classe MyClusterRenderer:

public class MyClusterRenderer extends DefaultClusterRenderer<MyItem> {

    private final IconGenerator mClusterIconGenerator = new IconGenerator(getApplicationContext());

    public MyClusterRenderer(Context context, GoogleMap map,
                             ClusterManager<MyItem> clusterManager) {
        super(context, map, clusterManager);
    }

    @Override
    protected void onBeforeClusterItemRendered(MyItem item,
                                               MarkerOptions markerOptions) {

        BitmapDescriptor markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_Magenta);

        markerOptions.icon(markerDescriptor);
    }

    @Override
    protected void onClusterItemRendered(MyItem clusterItem, Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
    }

    @Override
    protected void onBeforeClusterRendered(Cluster<MyItem> cluster, MarkerOptions markerOptions){

        final Drawable clusterIcon = getResources().getDrawable(R.drawable.ic_lens_black_24dp);
        clusterIcon.setColorFilter(getResources().getColor(Android.R.color.holo_orange_light), PorterDuff.Mode.SRC_ATOP);

        mClusterIconGenerator.setBackground(clusterIcon);

        //modify padding for one or two digit numbers
        if (cluster.getSize() < 10) {
            mClusterIconGenerator.setContentPadding(40, 20, 0, 0);
        }
        else {
            mClusterIconGenerator.setContentPadding(30, 20, 0, 0);
        }

        Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
    }
}

Code de classe complet:

public class MapsActivity extends AppCompatActivity
        implements ClusterManager.OnClusterItemInfoWindowClickListener<MyItem> {

    private ClusterManager<MyItem> mClusterManager;
    private MyItem clickedClusterItem;
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_maps);

        setUpMapIfNeeded();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }


    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();

            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }

        }
    }

    private void setUpMap() {

        mMap.getUiSettings().setMapToolbarEnabled(true);
        mMap.getUiSettings().setZoomControlsEnabled(true);
        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        mClusterManager = new ClusterManager<>(this, mMap);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.779977,-122.413742), 10));

        mMap.setOnCameraChangeListener(mClusterManager);
        mMap.setOnMarkerClickListener(mClusterManager);

        mClusterManager.setRenderer(new MyClusterRenderer(this, mMap,
                mClusterManager));

        mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());

        mMap.setOnInfoWindowClickListener(mClusterManager); //added
        mClusterManager.setOnClusterItemInfoWindowClickListener(this); //added

        mClusterManager
                .setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MyItem>() {
                    @Override
                    public boolean onClusterItemClick(MyItem item) {
                        clickedClusterItem = item;
                        return false;
                    }
                });



        addItems();

        mClusterManager.getMarkerCollection().setOnInfoWindowAdapter(
                new MyCustomAdapterForItems());

    }

    private void addItems() {

        double latitude = 37.779977;
        double longitude = -122.413742;
        for (int i = 0; i < 10; i++) {
            double offset = i / 60d;

            double lat = latitude + offset;
            double lng = longitude + offset;
            MyItem offsetItem = new MyItem(lat, lng, "title " + i+1, "snippet " + i+1);
            mClusterManager.addItem(offsetItem);

        }

    }

    //added with edit
    @Override
    public void onClusterItemInfoWindowClick(MyItem myItem) {

        //Cluster item InfoWindow clicked, set title as action
        Intent i = new Intent(this, OtherActivity.class);
        i.setAction(myItem.getTitle());
        startActivity(i);

        //You may want to do different things for each InfoWindow:
        if (myItem.getTitle().equals("some title")){

            //do something specific to this InfoWindow....

        }

    }

    public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {

        private final View myContentsView;

        MyCustomAdapterForItems() {
            myContentsView = getLayoutInflater().inflate(
                    R.layout.info_window, null);
        }
        @Override
        public View getInfoWindow(Marker marker) {

            TextView tvTitle = ((TextView) myContentsView
                    .findViewById(R.id.txtTitle));
            TextView tvSnippet = ((TextView) myContentsView
                    .findViewById(R.id.txtSnippet));

            tvTitle.setText(clickedClusterItem.getTitle());
            tvSnippet.setText(clickedClusterItem.getSnippet());

            return myContentsView;
        }

        @Override
        public View getInfoContents(Marker marker) {
            return null;
        }
    }

    public class MyClusterRenderer extends DefaultClusterRenderer<MyItem> {

        private final IconGenerator mClusterIconGenerator = new IconGenerator(getApplicationContext());

        public MyClusterRenderer(Context context, GoogleMap map,
                                 ClusterManager<MyItem> clusterManager) {
            super(context, map, clusterManager);
        }

        @Override
        protected void onBeforeClusterItemRendered(MyItem item,
                                                   MarkerOptions markerOptions) {

            BitmapDescriptor markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_Magenta);

            markerOptions.icon(markerDescriptor);
        }

        @Override
        protected void onClusterItemRendered(MyItem clusterItem, Marker marker) {
            super.onClusterItemRendered(clusterItem, marker);
        }

        @Override
        protected void onBeforeClusterRendered(Cluster<MyItem> cluster, MarkerOptions markerOptions){

            final Drawable clusterIcon = getResources().getDrawable(R.drawable.ic_lens_black_24dp);
            clusterIcon.setColorFilter(getResources().getColor(Android.R.color.holo_orange_light), PorterDuff.Mode.SRC_ATOP);

            mClusterIconGenerator.setBackground(clusterIcon);

            //modify padding for one or two digit numbers
            if (cluster.getSize() < 10) {
                mClusterIconGenerator.setContentPadding(40, 20, 0, 0);
            }
            else {
                mClusterIconGenerator.setContentPadding(30, 20, 0, 0);
            }

            Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        }
    }
}

Résultat:

Lancement initial de l'application:

No clustering

Zoom arrière, quelques clusters:

initial clustering

En effectuant un nouveau zoom arrière, tous les marqueurs sont regroupés:

all Markers clustered

31
Daniel Nugent

Nous pouvons remplacer getColor dans CustomClusterRenderer.

public class CustomClusterRenderer extends DefaultClusterRenderer<CustomClusterItem> {

@Override
    protected int getColor(int clusterSize) {
        return Color.parseColor("#567238");
    }
}
23
Karina Sokolova

J'ai pris quelques méthodes de superclasse et les ai refaites en partie. Maintenant, j'ai de beaux clusters standard avec mes propres couleurs.

public class CustomClusterRenderer extends DefaultClusterRenderer<GoogleMapMarker> {

private final IconGenerator mIconGenerator;
private ShapeDrawable mColoredCircleBackground;
private SparseArray<BitmapDescriptor> mIcons = new SparseArray();
private final float mDensity;
private Context mContext;

public CustomClusterRenderer(Context context, GoogleMap map,
                             ClusterManager<GoogleMapMarker> clusterManager) {
    super(context, map, clusterManager);


    this.mContext = context;
    this.mDensity = context.getResources().getDisplayMetrics().density;
    this.mIconGenerator = new IconGenerator(context);
    this.mIconGenerator.setContentView(this.makeSquareTextView(context));
    this.mIconGenerator.setTextAppearance(
            com.google.maps.Android.R.style.ClusterIcon_TextAppearance);
    this.mIconGenerator.setBackground(this.makeClusterBackground());
}

@Override
protected void onBeforeClusterRendered(Cluster<GoogleMapMarker> cluster,
                                       MarkerOptions markerOptions) {
    // Main color
    int clusterColor = mContext.getResources().getColor(R.color.colorPrimary);

    int bucket = this.getBucket(cluster);
    BitmapDescriptor descriptor = this.mIcons.get(bucket);
    if(descriptor == null) {
        this.mColoredCircleBackground.getPaint().setColor(clusterColor);
        descriptor = BitmapDescriptorFactory.fromBitmap(
                this.mIconGenerator.makeIcon(this.getClusterText(bucket)));
        this.mIcons.put(bucket, descriptor);
    }

    markerOptions.icon(descriptor);
}

private SquareTextView makeSquareTextView(Context context) {
    SquareTextView squareTextView = new SquareTextView(context);
    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(-2, -2);
    squareTextView.setLayoutParams(layoutParams);
    squareTextView.setId(com.google.maps.Android.R.id.text);
    int twelveDpi = (int)(12.0F * this.mDensity);
    squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi);
    return squareTextView;
}

private LayerDrawable makeClusterBackground() {
    // Outline color
    int clusterOutlineColor = mContext.getResources().getColor(R.color.colorWhite);

    this.mColoredCircleBackground = new ShapeDrawable(new OvalShape());
    ShapeDrawable outline = new ShapeDrawable(new OvalShape());
    outline.getPaint().setColor(clusterOutlineColor);
    LayerDrawable background = new LayerDrawable(
            new Drawable[]{outline, this.mColoredCircleBackground});
    int strokeWidth = (int)(this.mDensity * 3.0F);
    background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
    return background;
}

Et puis définissez le rendu sur Cluster Manager

mClusterManager = new ClusterManager<>(context, mGoogleMap);
mClusterManager.setRenderer(new CustomClusterRenderer(context, mGoogleMap, mClusterManager));
11
sWift

Joli rendu personnalisé avec texte centré et différentes tailles de clusters:

  public class MyClusterRenderer extends DefaultClusterRenderer<Station> {

    private final IconGenerator mClusterIconGeneratorBig = new IconGenerator(getCtx());
    private final IconGenerator mClusterIconGeneratorMed = new IconGenerator(getCtx());
    private final IconGenerator mClusterIconGeneratorSml = new IconGenerator(getCtx());
    final Drawable clusterIconBig = getResources().getDrawable(R.drawable.marker1);
    final Drawable clusterIconMed = getResources().getDrawable(R.drawable.marker2);
    final Drawable clusterIconSml = getResources().getDrawable(R.drawable.marker3);

    public MyClusterRenderer(Context context, GoogleMap map,
                             ClusterManager<Station> clusterManager) {
        super(context, map, clusterManager);
        setupIconGen(mClusterIconGeneratorBig, clusterIconBig, context);
        setupIconGen(mClusterIconGeneratorMed, clusterIconMed, context);
        setupIconGen(mClusterIconGeneratorSml, clusterIconSml, context);
    }

    private void setupIconGen(IconGenerator generator, Drawable drawable, Context context) {
        TextView textView = new TextView(context);
        textView.setTextAppearance(context, R.style.BubbleText);
        textView.setTypeface(App.FONTS[2]);
        textView.setId(com.google.maps.Android.R.id.amu_text);
        textView.setGravity(Android.view.Gravity.CENTER);
        textView.setLayoutParams(new FrameLayout.LayoutParams(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()));
        generator.setContentView(textView);
        generator.setBackground(drawable);
    }

    @Override
    protected void onBeforeClusterItemRendered(Station item, MarkerOptions markerOptions) {
        BitmapDescriptor markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_Magenta);
        markerOptions.icon(markerDescriptor);
    }

    @Override
    protected void onClusterItemRendered(Station clusterItem, Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
    }

    @Override
    protected void onBeforeClusterRendered(Cluster<Station> cluster, MarkerOptions markerOptions) {
        if (cluster.getSize() > 20) {
            Bitmap icon = mClusterIconGeneratorBig.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        } else if (cluster.getSize() > 10) {
            Bitmap icon = mClusterIconGeneratorMed.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        } else {
            Bitmap icon = mClusterIconGeneratorSml.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        }
    }

    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        return cluster.getSize() > 5;
    }
}

enter image description here

4
Hox

Accédez à DefaultClusterRenderer (package com.google.maps.Android.clustering.view;) et changez la méthode getColor () en ceci:

private int getColor(int clusterSize) {
        // custom color
        double _logClusterSize; // log
        final int _maxRed = Integer.parseInt("ff", 16);
//        Log.v("kai", String.valueOf(_maxRed));
        final int _minRed = Integer.parseInt("e6", 16);
        final int _maxGreen = Integer.parseInt("a2", 16);
        final int _minGreen = Integer.parseInt("47", 16);
        final int _maxBlue = Integer.parseInt("93", 16);
        final int _minBlue = Integer.parseInt("2d", 16);
        final double _maxLogClusterSize = 10;
        double _step = (_maxRed - _minRed) / _maxLogClusterSize;

        _logClusterSize = Math.log(clusterSize);
        if(_logClusterSize > 10) _logClusterSize = 10;

        int _red = _maxRed - (int) (_step * _logClusterSize);
        int _green = _maxGreen - (int) (_step * _logClusterSize);
        int _blue = _maxBlue - (int) (_step * _logClusterSize);

        return Color.rgb(_red, _green, _blue);

//        final float hueRange = 220;
//        final float sizeRange = 300;
//        final float size = Math.min(clusterSize, sizeRange);
//        final float hue = (sizeRange - size) * (sizeRange - size) / (sizeRange * sizeRange) * hueRange;
//        return Color.HSVToColor(new float[]{
//                hue, 1f, .6f
//        });
    }

Cela changera la couleur du cluster en rose, dans la plage de la couleur définie par le min (max) rouge (vert, bleu). J'espère que cette aide!

3
Kai Wang