2015-06-21 3 views
15

Есть ли способ изменить цвет фона элемента кластера? (тот, который отображает количество маркеров, например 100+, 200+ ...). Я попытался изучить исходный код ClusterManager, но не смог найти какой-либо вариант изменения цвета, но, возможно, кто-то здесь знает, как это сделать. Я в основном хочу немного «материализировать» эти цвета.Android maps utils значок значка кластера

ответ

21

Я смог получить грубую реализацию, используя this demo из образцов библиотеки в качестве руководства.

Я использовал значок lens из Иконки дизайна материалов от here. После загрузки lens zip я положил ic_lens_black_24dp.png под выпадающую папку. Затем я использовал метод Drawable.setColorFilter() для изменения цвета по умолчанию в коде.

Я также смог изменить цвет маркера по умолчанию, и подумал, что я включу это также здесь.

Во-первых, установить видеообработки по телефону setRenderer():

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

Затем определяют 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)); 
    } 
} 

Полный код класса:

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

Результат:

Начальное приложение запуска:

No clustering

Уменьшение масштаба, некоторые кластеризация:

initial clustering

Увеличение снова, все маркеры кластерный:

all Markers clustered

+0

Спасибо. Смогу ли я иметь разные цвета, такие как синий для 5 и красный для 10? – qwertz

+0

@qwertz Да, вы должны иметь возможность использовать 'cluster.getSize()' и соответственно менять цвет кластера. –

+0

Хорошо, спасибо :) – qwertz

9

Я взял некоторые методы суперкласса и частично переделать их. Теперь у меня есть красивые стандартные кластеры с собственными цветами.

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

А затем установить рендерер Cluster Manager

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

Спасибо, я проверю его – qwertz

+0

Это волшебство в виде кода. Спасибо! – danguilherme

+0

mColoredCircleBackground.getPaint() .setColor (clusterColor), не работает над кодом выпуска. Я имею в виду подписанный apk. Любой другой способ для этого? – Panache

3

Перейти к DefaultClusterRenderer (пакет com.google.maps.android.clustering.view;), и изменить метод GetColor() к этому:

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

Это изменит цвет на розовый кластера, в диапазоне от цвета, определенного мин (макс) красный (зеленый, синий). Надеюсь, что поможет!

+0

Это по далекий лучший ответ –

+0

Я не думаю, что изменение исходного кода библиотеки имеет большую помощь. Оно сделает ошибки в библиотеках уязвимыми. – Leukipp

13

Мы можем переопределить getColor в CustomClusterRenderer.

public class CustomClusterRenderer extends DefaultClusterRenderer<CustomClusterItem> { 

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

Th ank you, отличное решение! –

+0

способ использования? Когда я просто добавляю этот код в свой проект, он показывает мне ошибку - в конструкторе com.google.maps.clustering.view нет конструктора по умолчанию. DefaultClusterRenderer ' – kashlo

+0

Лучшие решения, как правило, просты. – okkko

0

Хороший пользовательский рендерер с центром текста и различных размеров кластеров:

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