问题
I'm trying to layout a custom infoWindow programmatically. I want to load a streetView preview image using Picasso but the image isn't showing up, any idea why?
private View prepareInfoView(Marker marker){
//prepare InfoView programmatically
LinearLayout infoView = new LinearLayout(EarthquakeActivity.this);
LinearLayout.LayoutParams infoViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
infoView.setOrientation(LinearLayout.VERTICAL);
// attach the above layout to the infoView
infoView.setLayoutParams(infoViewParams);
//create street view preview @ top
ImageView streetViewPreviewIV = new ImageView(EarthquakeActivity.this);
// this scales the image to match parents WIDTH?, but retain image's height??
LinearLayout.LayoutParams streetViewImageViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
streetViewPreviewIV.setLayoutParams(streetViewImageViewParams);
String imageURL = "https://maps.googleapis.com/maps/api/streetview?size=200x200&location=";
String markerLongitude = Double.toString(marker.getPosition().longitude);
String markerLatitude = Double.toString(marker.getPosition().latitude);
imageURL += markerLatitude + "," + markerLongitude + "&fov=120&heading=0&pitch=0";
Log.wtf("prepareInfoView", imageURL);
Picasso.with(this).load(imageURL).into(streetViewPreviewIV);
infoView.addView(streetViewPreviewIV);
I've tried with and without the api key appending the url.
It did work for a few clicks without the key, but hasn't since, with or without. Is the because it's too slow fetching it so Android gives up and loads the info window without it? Is there a best in class way to do this?
Would another image loading library work better? Google's volley?
Also with
LinearLayout.LayoutParams
I'd like the image to stretch across the width of the info windows, i.e. match_parent, and to scale vertically to maintain original aspect ratio, how do I do this?
This is my answer
In commonsWare new class I add this flag:
@Override
public void onSuccess() {
Log.i(TAG, "image got, should rebuild window");
if (marker != null && marker.isInfoWindowShown()) {
Log.i(TAG, "conditions met, redrawing window");
marker.setTag(new Boolean("True"));
marker.showInfoWindow();
}
}
And in prepareInfoView, I test for the flags absence.
if (marker.getTag() == null ) {
Log.i("prepareInfoView", "fetching image");
Picasso.with(this).load(imageURL).fetch(new MarkerCallback(marker));
}
else {
Log.wtf("prepareInfoView", "building info window");
Party on! :)
回答1:
Is the because it's too slow fetching it so Android gives up and loads the info window without it?
Picasso loads asynchronously unless the image is cached. And the way Maps V2 works is that the View
you return is converted into a Bitmap
, and that is what gets rendered. As a result, you have a race condition between Picasso and Maps V2 (does the image get loaded before the Bitmap
gets created?), and so it is indeterminate as to whether or not any given info window will work.
You can call showInfoWindow()
on the Marker
after Picasso has loaded the image, so you can populate the ImageView
from Picasso's cache. showInfoWindow()
, called on a Marker
, triggers Maps V2 to regenerate the info window.
For example, you could change your existing into()
call into into(streetViewPreviewIV, new MarkerCallback(marker))
, with a MarkerCallback
like:
static class MarkerCallback implements Callback {
Marker marker=null;
MarkerCallback(Marker marker) {
this.marker=marker;
}
@Override
public void onError() {
Log.e(getClass().getSimpleName(), "Error loading thumbnail!");
}
@Override
public void onSuccess() {
if (marker != null && marker.isInfoWindowShown()) {
marker.showInfoWindow();
}
}
}
Would another image loading library work better? Google's volley?
They will all suffer from the same issue.
回答2:
What is working for me is this:
public class MarkerCallback implements Callback {
Marker marker=null;
String URL;
ImageView userPhoto;
MarkerCallback(Marker marker, String URL, ImageView userPhoto) {
this.marker=marker;
this.URL = URL;
this.userPhoto = userPhoto;
}
@Override
public void onError() {
//Log.e(getClass().getSimpleName(), "Error loading thumbnail!");
}
@Override
public void onSuccess() {
if (marker != null && marker.isInfoWindowShown()) {
marker.hideInfoWindow();
Picasso.with(getActivity())
.load(URL)
.into(userPhoto);
marker.showInfoWindow();
}
}
}
回答3:
All I figured out is, Picasso loads image asynchronously, so when a marker shows it's info window after clicking by internally calling the method getInfoContents or getInfoWindow method , by this time if the image isn't already downloaded or cached by Picasso , then it is not showed on infoWindow. Picasso tries to load the image into imageview of infoWindow when downloaded, but According to Google maps V2, the infoWindows Once loaded, can't be manipulated, so image is not shown updated on the UI. But the infowindow view was updated actually but couldn't show for the restriction, so if you just hide and show the infowindow , it is kind of refreshed, and the images are shown on updated infoWindow. you can do this in the following way,
You need to keep the marker reference, you can keep this as Activity/Fragment's member variable.
Picasso.with(context)
.load(marker.getSnippet())
.placeholder(R.drawable.ic_placeholder)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
if (currentClickedMarker != null && currentClickedMarker.isInfoWindowShown()) {
//toggle the marker's infoWindow
currentClickedMarker.hideInfoWindow();
currentClickedMarker.showInfoWindow();
}
}
@Override
public void onError() {
}
});
回答4:
I struggled with this as well, here is a solution with glide inspired from the accepted answer.
This solution did not work for me without resizing the picture to a proper size. With override()
(and centerCrop
) it did the trick.
Keep track of the latest picture shown
private String previousImageUrl = null;
And use it to see if you need refreshing of the current image
googleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
return null;
}
@Override
public View getInfoContents(final Marker marker) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_map_info_window, null);
MyObject myObject = (MyObject) marker.getTag();
final String url = myObject.getImageUrl();
final ImageView imageView = (ImageView) view.findViewById(R.id.image_view);
GlideApp.with(getContext()).load(url)
.override(imageWidth, imageHeight) // made the difference
.centerCrop()
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
imageView.setImageDrawable(resource);
if (!TextUtils.equals(url, previousImageUrl)) {
previousImageUrl = url;
marker.showInfoWindow();
}
}
});
return view;
}
});
回答5:
If you are using the accepted answer to fix the problem and it still doesn't work, you're probably using .fit() . in other words you should remove .fit() from your Picasso code. It took me a couple hours to realize it.
来源:https://stackoverflow.com/questions/39551774/picasso-image-not-loading-in-custom-infowindow-why