Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Glide not renders images to markers in clusters when on first time map loaded. It loads images after once zoom in and zoom out the map #417

Closed
satheesh1000 opened this issue Aug 24, 2017 · 9 comments
Labels
Milestone

Comments

@satheesh1000
Copy link

I am using cluster in my map and created custom markers with images and using glide to download images from url and render it to my markers. But what my problem is on first time when my map loaded images are are not rendered to markers. After some zoom in zoom out the map only the glide start to download the images. But I want to download images at first call of map loading.If i use URL stream download it works fine. But that will download every time the images. Anybody please help me to resolve this problem. Here after I have attached my code.

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterItem;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;
import com.google.maps.android.ui.IconGenerator;
import com.google.maps.android.utils.demo.model.Person;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Demonstrates heavy customisation of the look of rendered clusters.
 */
public class CustomMarkerClusteringDemoActivity2 extends FragmentActivity implements OnMapReadyCallback,ClusterManager.OnClusterClickListener<Person>, ClusterManager.OnClusterInfoWindowClickListener<Person>, ClusterManager.OnClusterItemClickListener<Person>, ClusterManager.OnClusterItemInfoWindowClickListener<Person> {
    private ClusterManager<Person> mClusterManager;
    private Random mRandom = new Random(1984);


    private GoogleMap mMap;

    protected int getLayoutId() {
        return R.layout.map;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        setUpMap();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMap();
    }

    @Override
    public void onMapReady(GoogleMap map) {
        if (mMap != null) {
            return;
        }
        mMap = map;
        startDemo();
    }

    private void setUpMap() {
        ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);
    }

    protected GoogleMap getMap() {
        return mMap;
    }

    /**
     * Draws profile photos inside markers (using IconGenerator).
     * When there are multiple people in the cluster, draw multiple photos (using MultiDrawable).
     */
    private class PersonRenderer extends DefaultClusterRenderer<Person> {
        private final IconGenerator mIconGenerator = new IconGenerator(getApplicationContext());
        private final IconGenerator mClusterIconGenerator = new IconGenerator(getApplicationContext());
        private final ImageView mImageView;
        private final ImageView mClusterImageView;
        private final int mDimension;

        public PersonRenderer() {
            super(getApplicationContext(), getMap(), mClusterManager);

            View multiProfile = getLayoutInflater().inflate(R.layout.multi_profile, null);
            mClusterIconGenerator.setContentView(multiProfile);
            mClusterImageView = (ImageView) multiProfile.findViewById(R.id.image);

            mImageView = new ImageView(getApplicationContext());
            mDimension = (int) getResources().getDimension(R.dimen.custom_profile_image);
            mImageView.setLayoutParams(new ViewGroup.LayoutParams(mDimension, mDimension));
            int padding = (int) getResources().getDimension(R.dimen.custom_profile_padding);
            mImageView.setPadding(padding, padding, padding, padding);
            mIconGenerator.setContentView(mImageView);
        }

        @Override
        protected void onBeforeClusterItemRendered(Person person, MarkerOptions markerOptions) {
            Glide.with(CustomMarkerClusteringDemoActivity2.this)
                    .load(person.profilePhoto).asBitmap()
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .fitCenter()
                    .placeholder(R.drawable.ic_launcher).dontAnimate().into(mImageView);

            //            URL url = null;
//            try {
//                url = new URL(person.profilePhoto);
//                Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
//                mImageView.setImageBitmap(bmp);
//            } catch (MalformedURLException e) {
//                e.printStackTrace();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }

            Bitmap icon = mIconGenerator.makeIcon();
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(person.name);
        }

        @Override
        protected void onBeforeClusterRendered(Cluster<Person> cluster, MarkerOptions markerOptions) {
            // Draw multiple people.
            // Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).
            List<Drawable> profilePhotos = new ArrayList<Drawable>(Math.min(4, cluster.getSize()));
            int width = mDimension;
            int height = mDimension;
            Bitmap dummyBitmap=null;
            Drawable drawable=null;

            for (Person p : cluster.getItems()) {
                // Draw 4 at most.
                if (profilePhotos.size() == 4) break;
                try {

                    dummyBitmap = Glide.with(getApplicationContext()).load(p.profilePhoto)
                            .asBitmap().into(70,70).get();

                } catch (Exception e) {
                    e.printStackTrace();
                }
                drawable = new BitmapDrawable(getResources(), dummyBitmap);
                drawable.setBounds(0, 0, width, height);
                profilePhotos.add(drawable);
            }

            MultiDrawable multiDrawable = new MultiDrawable(profilePhotos);
            multiDrawable.setBounds(0, 0, width, height);

            mClusterImageView.setImageDrawable(multiDrawable);
            Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        }

        @Override
        protected boolean shouldRenderAsCluster(Cluster cluster) {
            // Always render clusters.
            return cluster.getSize() > 1;
        }
    }

    @Override
    public boolean onClusterClick(Cluster<Person> cluster) {
        // Show a toast with some info when the cluster is clicked.
        String firstName = cluster.getItems().iterator().next().name;
        Toast.makeText(this, cluster.getSize() + " (including " + firstName + ")", Toast.LENGTH_SHORT).show();

        // Zoom in the cluster. Need to create LatLngBounds and including all the cluster items
        // inside of bounds, then animate to center of the bounds.

        // Create the builder to collect all essential cluster items for the bounds.
        LatLngBounds.Builder builder = LatLngBounds.builder();
        for (ClusterItem item : cluster.getItems()) {
            builder.include(item.getPosition());
        }
        // Get the LatLngBounds
        final LatLngBounds bounds = builder.build();

        // Animate camera to the bounds
        try {
            getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    @Override
    public void onClusterInfoWindowClick(Cluster<Person> cluster) {
        // Does nothing, but you could go to a list of the users.
    }

    @Override
    public boolean onClusterItemClick(Person item) {
        // Does nothing, but you could go into the user's profile page, for example.
        return false;
    }

    @Override
    public void onClusterItemInfoWindowClick(Person item) {
        // Does nothing, but you could go into the user's profile page, for example.
    }

    protected void startDemo() {
        getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(9.9252,78.1198), 8f));

        mClusterManager = new ClusterManager<Person>(this, getMap());
        mClusterManager.setRenderer(new PersonRenderer());
        getMap().setOnCameraIdleListener(mClusterManager);
        getMap().setOnMarkerClickListener(mClusterManager);
        getMap().setOnInfoWindowClickListener(mClusterManager);
        mClusterManager.setOnClusterClickListener(this);
        mClusterManager.setOnClusterInfoWindowClickListener(this);
        mClusterManager.setOnClusterItemClickListener(this);
        mClusterManager.setOnClusterItemInfoWindowClickListener(this);

        addItems();
        mClusterManager.cluster();
    }

    private void addItems() {
        mClusterManager.addItem(new Person(new LatLng(9.9252,78.1198), "Madurai",  "https://images.techhive.com/images/article/2016/09/android-old-habits-100682662-primary.idge.jpg"));

        mClusterManager.addItem(new Person(new LatLng(13.0827,80.2707), "Chennai", "https://images.techhive.com/images/article/2016/09/android-old-habits-100682662-primary.idge.jpg"));

        mClusterManager.addItem(new Person(new LatLng(10.9675,76.9182), "Covai", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSppY02DkBSDtdnf8EVLKm7-n_0AlO1v5NKCcMWeVdzZ0VkIIiECA"));

        mClusterManager.addItem(new Person(new LatLng(10.7905,78.7047), "Trichy", "http://4.bp.blogspot.com/-8v_k_fOcfP8/UQIL4ufghBI/AAAAAAAAEDo/9ffRRTM9AnA/s1600/android-robog-alone.png"));

        mClusterManager.addItem(new Person(new LatLng(10.3673,77.9803), "Dindigul", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRArxJKW72owkwK0zD60Q_GJiVg36vy80Xf1dBPGBk87AefQa5e"));

//        mClusterManager.addItem(new Person(position(), "Yeats", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3Ab0euUF-ClwheIfODe04krTeGIkD-wf-gYQcaZWhAHzD4nOp"));
//
//        mClusterManager.addItem(new Person(position(), "John", "http://www.jrtstudio.com/sites/default/files/ico_android.png"));
//
//        mClusterManager.addItem(new Person(position(), "Trevor the Turtle", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmVSoCOR98Vw7iqlm-LWjZ_iTt5ZhvMy8TqUb7zyKNj4VoSWhZ"));
//
//        mClusterManager.addItem(new Person(position(), "Teach1", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuYdYnhMjcvd4hAH3-5hvPavCgb3b_8Rs6UTtviCoOTpIEwvig"));
//
//        mClusterManager.addItem(new Person(position(), "Teach2", "http://www.lyps.edu.hk/wp-content/uploads/2014/08/unnamed.png"));
//
//        mClusterManager.addItem(new Person(position(), "Teach3", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTVdtXystrbg1tU-WzII4Tbp7oWBgDZ_RmDVpCxTgwGyEEOrh6bxg"));
//
//        mClusterManager.addItem(new Person(position(), "Teach4", "https://lh4.ggpht.com/KZpaG6K6Q7JV9CqN7uKfapGwZoK3PLEeZYbALpMO1sY4jJ4FPbYY12Uu-wY2vO9xXZE=w300"));
//
//        mClusterManager.addItem(new Person(position(), "Teach5", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTDmE3crCrCt4lnMZPzaPLna3xRZwCG-x1_adS98fRebfU_aYlZXg"));
//
//        mClusterManager.addItem(new Person(position(), "Teach6", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRiMaki37C4rnhvKOUXyuIGuDxm-sfNiC-jkqU9WkXx-yj8PvqDvw"));
//
//        mClusterManager.addItem(new Person(position(), "Teach7", "https://lh3.ggpht.com/wFQnMKpl6M1JGhG2nfGY5WGiZqWBkKTsGkFLngwQxjKbEBN6bpAh3ljUu3KQVozH0sI=w300"));
//
//        mClusterManager.addItem(new Person(position(), "Teach8", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTodrOHInZLLQmkA9H_0OBg472_OROG47GoEB53HFi5O3fZYmi7bA"));
    }

    private LatLng position() {
        return new LatLng(random(51.6723432, 51.38494009999999), random(0.148271, -0.3514683));
    }

    private double random(double min, double max) {
        return mRandom.nextDouble() * (max - min) + min;
    }
}

Thanks in advance...

@tqkhanh29
Copy link

No idea?

@EkslV
Copy link

EkslV commented Oct 3, 2018

same problem...

@dipakksharma
Copy link

Same Problem...

@ChetnaNakum
Copy link

Same problem

@tanujsareen
Copy link

@satheesh1000 Find any solution ??

@kujaomega
Copy link

Same Problem

@donghae0414
Copy link

i figured out this problem with override onClusterRendered not override onBeforeClusterRendered
but i have a problem that the number of cluster items differs from the number shown on the map.

@c1scok1d
Copy link

Hello,

I am having the same issue, could you please share your fix for getting the images to display? It also appears that the cluster number is differing because it adds the same markers so everything is doubled.

@arriolac arriolac added triage me I really want to be triaged. help wanted We'd love to have community involvement on this issue. labels Jan 16, 2020
@arriolac arriolac added status: duplicate Duplicate. and removed help wanted We'd love to have community involvement on this issue. triage me I really want to be triaged. labels Jan 29, 2020
@arriolac
Copy link
Contributor

Thank you for reporting. This is a duplicate issue as the one described in #90.

Essentially, updating the marker icon once an initial one has been set (synchronously) in onBeforeClusterItemRendered is not currently possible. You can follow the discussion in #90 for a possible workaround.

In the case of Glide/Picasso/Fresco/etc., you would have to prefetch the marker images and cache them locally. Once that's completed, only then can you add each individual item followed by invoking cluster().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants