Reputation: 2798
I'm trying to load dynamically users avatars as custom markers. I based my code on the google maps utils demo, but somehow it doesn't work, it loads only one image and all the others are empty:
Here is my code:
public class MapsActivity extends FragmentActivity implements ClusterManager.OnClusterItemClickListener<ModelUser>, ClusterManager.OnClusterItemInfoWindowClickListener<ModelUser> {
private ClusterManager<ModelUser> mClusterManager;
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private QueryAPI query = new QueryAPI();
private List<ModelUser> users = new ArrayList<ModelUser>();
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
//UI
NetworkImageView avatarImageView;
TextView name;
TextView infos;
TextView distance;
RelativeLayout detailView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
detailView = (RelativeLayout) findViewById(R.id.detailView);
avatarImageView = (NetworkImageView) findViewById(R.id.imageView);
name = (TextView) findViewById(R.id.name);
infos = (TextView) findViewById(R.id.info);
distance = (TextView) findViewById(R.id.distance);
query.nearUsers(new QueryAPI.ApiResponse<List<ModelUser>>() {
@Override
public void onCompletion(List<ModelUser> result) {
users = result;
setUpClusterer();
}
});
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMap() {
mMap.setMyLocationEnabled(true);
}
private void setUpClusterer() {
// Position the map.
getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(46.155115, 2.473060), 5));
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<ModelUser>(this, getMap());
// Point the map's listeners at the listeners implemented by the cluster
// manager.
getMap().setOnCameraChangeListener(mClusterManager);
getMap().setOnMarkerClickListener(mClusterManager);
mClusterManager.setRenderer(new PersonRenderer());
mClusterManager.setOnClusterItemClickListener(this);
mClusterManager.setOnClusterItemInfoWindowClickListener(this);
// Add cluster items (markers) to the cluster manager.
addItems();
}
private void addItems() {
for (int i = 0; i < users.size(); i++) {
ModelUser user = users.get(i);
mClusterManager.addItem(user);
}
}
protected GoogleMap getMap() {
setUpMapIfNeeded();
return mMap;
}
@Override
public boolean onClusterItemClick(ModelUser item) {
Log.d("User clicked:", item.getName());
avatarImageView.setImageUrl(item.getAvatar_url(), imageLoader);
name.setText(item.getName());
infos.setText(item.getAge());
double d = Double.parseDouble(item.getDistance());
distance.setText( String.format("%.1f", d) + "Km");
detailView.setVisibility(View.VISIBLE);
return false;
}
@Override
public void onClusterItemInfoWindowClick(ModelUser item) {
Log.d("User Window clicked:", item.getName());
}
/**
* 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<ModelUser> {
private final IconGenerator mIconGenerator = new IconGenerator(getApplicationContext());
private final UICircularImage mImageView;
//private final int mDimension;
public PersonRenderer() {
super(getApplicationContext(), getMap(), mClusterManager);
View profile = getLayoutInflater().inflate(R.layout.map_marker_item, null);
mIconGenerator.setContentView(profile);
mImageView = (UICircularImage) profile.findViewById(R.id.avatarImageView);
}
@Override
protected void onBeforeClusterItemRendered(ModelUser user, MarkerOptions markerOptions) {
// Draw a single person.
// Set the info window to show their name.
// mImageView.setImageUrl(user.getAvatar_url(), imageLoader);
Picasso.with(getApplicationContext())
.load(user.getAvatar_url())
.noFade()
.into(mImageView, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
//reload the marker HERE
}
@Override
public void onError() {
}
});
Bitmap icon = mIconGenerator.makeIcon();
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(user.getName());
}
}
Any idea why?
EDIT: I realized that sometimes it does load all the images, I think the problem comes from the async task. So my question is now: if I implement a callback to know when Picasso has finished to load the image, how can I reload this specific marker?
Upvotes: 4
Views: 4899
Reputation: 2465
Regarding about @Stas Parshin answer, there might be some problems with Glide if you put the request within onBeforeClusterItemRendered()
.
I placed it on onClusterItemRendered()
and it worked beautifully. It is because Glide is using asynchronous process and might not able to load it into ImageView
in time.
Hope it helps.
Upvotes: 1
Reputation: 2632
hello man the previous answer is working with with libs and here is another answer with native code
private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
ImageView image;
LatLng latLng;
public DownloadImage (double lat, double lng) {
this.latLng = new LatLng(lat, lng);
}
protected Bitmap doInBackground(String... urls) {
String url = urls[0];
Bitmap bmpImg = null;
try {
InputStream in = new java.net.URL(url).openStream();
bmpImg = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("image", e.toString());
}
return bmpImg;
}
protected void onPostExecute(Bitmap bmpImg) {
View viewLocationMarker = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.marker_custom_view, null);
ImageView imageView = (ImageView) viewLocationMarker.findViewById(R.id.imgPic);
try {
imageView.setImageBitmap(bmpImg);
} catch (Exception e) {
imageView.setImageResource(R.drawable.place_holder);
}
Marker locationMarker = mMap.addMarker(new MarkerOptions()
.position(latLng).title("Sattar").anchor(0.33f, 1)
.icon(BitmapDescriptorFactory.fromBitmap(createDrawableFromView(MapsActivity.this, viewLocationMarker))));
}
}
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Upvotes: 1
Reputation: 8283
We'll load raw bitmap from Picasso and then pass it to marker representing current user
Picasso.with(getApplicationContext())
.load(user.getAvatar_url())
.into(new com.squareup.picasso.Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
// let's find marker for this user
Marker markerToChange = null;
for (Marker marker : mClusterManager.getMarkerCollection().getMarkers()) {
if (marker.getPosition().equals(user.getPosition())) {
markerToChange = marker;
break;
}
}
// if found - change icon
if (markerToChange != null) {
markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
I have some troubles with Picasso too. So, i recommend to use Glide
compile 'com.github.bumptech.glide:glide:3.5.2'
Glide.with(getApplicationContext()).
load(user.getAvatar_url())
.asBitmap()
.fitCenter()
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
// let's find marker for this user
Marker markerToChange = null;
for (Marker marker : mClusterManager.getMarkerCollection().getMarkers()) {
if (marker.getPosition().equals(user.getPosition())) {
markerToChange = marker;
break;
}
}
// if found - change icon
if (markerToChange != null) {
markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
}
});
Upvotes: 6