Android карты utils кластер цвет значка
Есть ли способ изменить цвет фона элемента кластера? (тот, который отображает количество маркеров, например 100+, 200+ ...). Я попытался заглянуть в исходный код ClusterManager, но не смог найти никакой возможности изменить цвет, но, возможно, кто-то здесь знает, как это сделать. Я в основном хочу немного "материализовать" эти цвета.
5 ответов:
Я смог получить грубую реализацию, используя эту демонстрацию из образцов библиотеки в качестве руководства.
Я использовал значок
lens
из значков Material Design из здесь. После загрузкиlens
zip я поместилic_lens_black_24dp.png
в папку drawable. Затем я использовал 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)); } } }
Результат:
Начальный запуск приложения:
Уменьшение масштаба, некоторая кластеризация:
Масштабирование снова, все маркеры сгруппированы:
Мы можем переопределить getColor в CustomClusterRenderer.
public class CustomClusterRenderer extends DefaultClusterRenderer<CustomClusterItem> { @Override protected int getColor(int clusterSize) { return Color.parseColor("#567238"); } }
Я взял некоторые методы суперкласса и частично переделал их. Теперь у меня есть красивые стандартные кластеры с моими собственными цветами.
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; }
, а затем установите renderer в Cluster Manager
mClusterManager = new ClusterManager<>(context, mGoogleMap); mClusterManager.setRenderer(new CustomClusterRenderer(context, mGoogleMap, mClusterManager));
Перейдите в DefaultClusterRenderer (package com.гугл.карты.андроид.кластеризация.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 // }); }
Это изменит цвет кластера на розовый, в диапазоне цвета, определенного min(max) красный (зеленый, синий). Надеюсь, что поможет!
Хороший пользовательский рендерер с центрированным текстом и различными размерами кластеров:
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; } }