2015-06-21 8 views
15

Esiste un metodo per modificare il colore di sfondo dell'elemento del cluster? (quello che mostra il conteggio dei marker, come 100+, 200+ ...). Ho provato a cercare il codice sorgente di ClusterManager ma non sono riuscito a trovare alcuna opzione per cambiare il colore, ma forse qualcuno qui sa come farlo. Fondamentalmente voglio "materializzare" quei colori un po '.Le mappe Android utilizzano il colore dell'icona del cluster

risposta

21

Sono stato in grado di ottenere un'implementazione di massima lavorando utilizzando this demo dagli esempi di libreria come guida.

Ho utilizzato l'icona lens dalle icone del materiale di design da here. Dopo aver scaricato lo zip lens, inserisco ic_lens_black_24dp.png nella cartella drawable. Quindi ho utilizzato il metodo Drawable.setColorFilter() per modificare il colore predefinito nel codice.

Sono stato anche in grado di modificare il colore Marker predefinito e ho pensato che avrei incluso anche qui.

In primo luogo, impostare un renderer chiamando setRenderer():

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

Quindi, definire 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)); 
    } 
} 

codice della classe completa:

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

Risultato:

iniziale di lancio app:

No clustering

Zoom fuori, alcuni di clustering:

initial clustering

Zoom di nuovo, tutti i marcatori cluster:

all Markers clustered

+0

Grazie. Sarei in grado di avere colori diversi come il blu per 5 e il rosso per 10? – qwertz

+0

@qwertz Sì, dovresti essere in grado di utilizzare 'cluster.getSize()' e modificare di conseguenza il colore del cluster. –

+0

Ok, grazie :) – qwertz

9

ho preso un po ' metodi di superclasse e parzialmente rifatti. Ora ho bei grappoli standard con i miei colori.

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

e quindi impostare renderer di Cluster Manager

mClusterManager = new ClusterManager<>(context, mGoogleMap); 
mClusterManager.setRenderer(new CustomClusterRenderer(context, mGoogleMap, mClusterManager)); 
+0

Grazie, lo verificherò – qwertz

+0

Questa è magia sotto forma di codice. Grazie! – danguilherme

+0

mColoredCircleBackground.getPaint() .setColor (clusterColor); non funziona sul codice di rilascio. Voglio dire apk firmato. Qualsiasi altro modo per questo? – Panache

3

Vai DefaultClusterRenderer (pacchetto com.google.maps.android.clustering.view;), e modificare il metodo di getColor() per questo:

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

Questo cambierà il colore del cluster al rosa, nella gamma del colore definito da min (max) rosso (verde, blu). Spero che aiuto!

+0

Questo è da la risposta migliore è –

+0

Non credo che cambiare il codice sorgente di una libreria sia di grande aiuto, ma renderà gli aggiornamenti delle librerie soggette a errori – Leukipp

13

Possiamo eseguire l'override di getColor in CustomClusterRenderer.

public class CustomClusterRenderer extends DefaultClusterRenderer<CustomClusterItem> { 

@Override 
    protected int getColor(int clusterSize) { 
     return Color.parseColor("#567238"); 
    } 
} 
+0

Th ank te, ottima soluzione! –

+0

come si usa? Quando aggiungo questo codice al mio progetto mi viene visualizzato un messaggio di errore: non è disponibile un costruttore predefinito in "com.google.maps.clustering.view. DefaultClusterRenderer ' – kashlo

+0

Le migliori soluzioni sono in genere semplici. – okkko

0

renderer personalizzato Nizza con testo centrato e diverse dimensioni dei cluster:

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