简体   繁体   English

Android 地图 utils 集群图标颜色

[英]Android maps utils cluster icon color

Is there any method to change the background color of the cluster item?有没有什么方法可以改变集群项的背景颜色? (the one that displays the count of the markers, like 100+, 200+ ...). (显示标记计数的那个,例如 100+、200+ ...)。 I tried to look into the source code of the ClusterManager but could not find any option to change the color, but maybe someone here knows how to do that.我试图查看 ClusterManager 的源代码,但找不到任何更改颜色的选项,但也许这里有人知道如何做到这一点。 I basically want to "materialify" those colors a bit.我基本上想“具体化”这些颜色。

I was able to get a rough implementation working by using this demo from the library samples as a guide.通过使用库示例中的这个演示作为指导,我能够得到一个粗略的实现。

I used the lens icon from the Material Design Icons from here .我使用了来自此处的 Material Design Icons 中的lens图标。 After downloading the lens zip I put ic_lens_black_24dp.png under the drawable folder.下载lens压缩包后,我将ic_lens_black_24dp.png放在 drawable 文件夹下。 Then I used the Drawable.setColorFilter() method to change the default color in the code.然后我使用Drawable.setColorFilter()方法更改代码中的默认颜色。

I was also able to change the default Marker color, and figured I would include that as well here.我还能够更改默认的标记颜色,并认为我也会在这里包含它。

First, set a Renderer by calling setRenderer() :首先,通过调用setRenderer()设置渲染器:

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

Then, define the MyClusterRenderer class:然后,定义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));
    }
}

Full class code:全班代码:

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

Result:结果:

Initial app launch:初始应用程序启动:

无聚类

Zooming out, some clustering:缩小,一些聚类:

初始聚类

Zooming out again, all Markers clustered:再次缩小,所有标记都聚集在一起:

所有标记聚集

We can Override getColor in CustomClusterRenderer.我们可以在 CustomClusterRenderer 中覆盖 getColor。

public class CustomClusterRenderer extends DefaultClusterRenderer<CustomClusterItem> {

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

I took some methods of superclass and partially remade them.我采用了一些超类的方法并部分地重新制作了它们。 Now i have beautiful standard clusters with my own colors.现在我有漂亮的标准集群,有我自己的颜色。

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

And then set renderer to Cluster Manager然后将渲染器设置为集群管理器

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

Nice custom renderer with centered text and different sizes of 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;
    }
}

在此处输入图片说明

Go to DefaultClusterRenderer (package com.google.maps.android.clustering.view;), and change the getColor() method to this:转到 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
//        });
    }

This will change the Cluster color to pink, in the range of the color defined by min(max) red(green, blue).这会将集群颜色更改为粉红色,在 min(max) red(green, blue) 定义的颜色范围内。 Hope that help!希望有所帮助!

Sadly, overriding getColor doesn't work for me.可悲的是,覆盖getColor对我不起作用。 But this looks enough to change the marker color (and something else):但这看起来足以改变标记颜色(和其他东西):

class ClusterItemRenderer(
    context: Context, map: GoogleMap,
    clusterManager: ClusterManager<ClusterMarker>
) : DefaultClusterRenderer<ClusterMarker>(context, map, clusterManager) {

    override fun onBeforeClusterItemRendered(item: ClusterMarker, markerOptions: MarkerOptions) {
        val markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)
        markerOptions.icon(markerDescriptor)
    }
}

It's also possible to add updates according to the recommendations :也可以根据建议添加更新:

If you're using custom clustering (ie, if you're extending DefaultClusterRenderer ), you must override two additional methods in v1:如果您使用自定义集群(即,如果您扩展DefaultClusterRenderer ),则必须覆盖 v1 中的两个附加方法:

  • onClusterItemUpdated() - should be the same* as your onBeforeClusterItemRendered() method onClusterItemUpdated() - 应该与您的onBeforeClusterItemRendered()方法相同*
  • onClusterUpdated() - should be the same* as your onBeforeClusterRendered() method onClusterUpdated() - 应该与您的onBeforeClusterRendered()方法相同*

* Note that these methods can't be identical, as you need to use a Marker instead of MarkerOptions *请注意,这些方法不能相同,因为您需要使用Marker而不是MarkerOptions

override fun onClusterItemUpdated(item: ClusterMarker, marker: Marker) {
    val markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)
    marker.setIcon(markerDescriptor)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM