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...
No idea?
same problem...
Same Problem...
Same problem
@satheesh1000 Find any solution ??
Same Problem
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.
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.
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().