Android карты utils кластер цвет значка


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

5 17

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

Введите описание изображения здесь