Agregue una imagen de la url en InfoWindow personalizado google maps v2

Estoy trabajando en una aplicación de Android. El usuario hace una búsqueda en google maps para restaurantes. En los marcadores de visualización del mapa de Google para todos los restaurantes de su vecino. Si toca un marcador, aparece una ventana de información personalizada. Mi problema es que no puedo cargar la imagen que devuelve el formulario de Google. Estoy acertando con la URL de la imagen, pero no puedo mostrarla en Window.

InfoWindow

         

En crear tengo esto

 mGoogleMap.setInfoWindowAdapter(new InfoWindowAdapter() { // Use default InfoWindow frame @Override public View getInfoWindow(Marker arg0) { return null; } // Defines the contents of the InfoWindow @Override public View getInfoContents(Marker arg0) { // Getting view from the layout file info_window_layout View v = getLayoutInflater().inflate(R.layout.info_window_layout, null); // Getting the snippet from the marker String snippet = arg0.getSnippet(); // Getting the snippet from the marker String titlestr = arg0.getTitle(); String cutchar1= "%#"; String cutchar2= "%##"; String ratingstr = snippet.substring(0,snippet.indexOf( cutchar1 )); String vicinitystr = snippet.substring(snippet.indexOf( cutchar1 )+2, snippet.indexOf( cutchar2 ) ); String iconurl= snippet.substring(snippet.indexOf( cutchar2 )+3); // Getting reference to the TextView to set latitude TextView title = (TextView) v.findViewById(R.id.place_title); TextView vicinity = (TextView) v.findViewById(R.id.place_vicinity); ImageView image = (ImageView) v.findViewById(R.id.navigate_icon); // Setting the latitude title.setText(titlestr); // declare RatingBar object RatingBar rating=(RatingBar) v.findViewById(R.id.place_rating);// create RatingBar object if( !(ratingstr.equals("null")) ){ rating.setRating(Float.parseFloat(ratingstr)); } vicinity.setText(vicinitystr); final DownloadImageTask download = new DownloadImageTask((ImageView) v.findViewById(R.id.place_icon) ,arg0); download.execute(iconurl); // Returning the view containing InfoWindow contents return v; } 

});

y el código DownloadImage es:

 private class DownloadImageTask extends AsyncTask { ImageView bmImage; Marker marker; boolean refresh; public DownloadImageTask(final ImageView bmImage, final Marker marker) { this.bmImage = bmImage; this.marker=marker; this.refresh=false; } public void SetRefresh(boolean refresh ){ this.refresh=true; } /* @Override protected void onPreExecute() { super.onPreExecute(); bmImage.setImageBitmap(null); }*/ @Override protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mIcon11 = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mIcon11 = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mIcon11; } @Override protected void onPostExecute(Bitmap result) { if(!refresh){ SetRefresh(refresh); bmImage.setImageBitmap(result); marker.showInfoWindow(); } } } 

Finalmente, cuando ejecuto el código y toco el marcador, getInfoContents no deja de ejecutarse y el ícono no aparece.

¿Por qué sucede esto?

He estado construyendo una aplicación similar.

En primer lugar, la razón por la que InfoWindow no muestra la imagen descargada se debe a que MapFragment convierte la vista en un Canvas y luego la dibuja. Lo que estás viendo en la ventana de información no son las vistas que creaste, sino una “imagen” o “captura de pantalla” de ellas. Básicamente necesita llamar a showInfoWindow() nuevamente en el objeto Marker , y eso volverá a representar el Canvas y su imagen ahora estará visible.

Sin embargo, dicho esto, en mi experiencia cargar el Bitmap de Bitmap desde la URL y luego configurarlo no es la mejor solución. Android no maneja muy bien Bitmap . Después de cargar varios mapas de bits, una excepción OutOfMemoryError es solo una cuestión de tiempo, dependiendo de la cantidad de memoria del sistema que tenga.

Recomiendo usar la biblioteca Picasso, que maneja la descarga asíncrona y el almacenamiento en caché (en memoria y disco) y hace que la imagen real cargue solo una línea ( Picasso.with(context).load("http://sofes.miximages.com/android/DvpvklR.jpg").into(imageView); ). (más información en http://square.github.io/picasso/ )

La respuesta anterior fue buena, excepto que, como dijo, ese “retraso” es un poco mágico para mi gusto. Picasso tiene la opción de usar devoluciones de llamada, y recomendaría usar eso (estoy usando eso en mi aplicación).

Primero crea una clase (puede ser interna para tu actividad) que implementa la interfaz Callback de Picasso y recibe un Marker en el constructor (para que puedas llamar a showInfoWindow() en ese marcador nuevamente.

 private class InfoWindowRefresher implements Callback { private Marker markerToRefresh; private InfoWindowRefresher(Marker markerToRefresh) { this.markerToRefresh = markerToRefresh; } @Override public void onSuccess() { markerToRefresh.showInfoWindow(); } @Override public void onError() {} } 

La ventana de información se ve así:

 mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { @Override public View getInfoWindow(Marker marker) { // inflate view window // set other views content // set image view like this: if (not_first_time_showing_info_window) { Picasso.with(ActivityClass.this).load(restaurantPictureURL).into(imgInfoWindowPicture); } else { // if it's the first time, load the image with the callback set not_first_time_showing_info_window=true; Picasso.with(ActivityClass.this).load(restaurantPictureURL).into(imgInfoWindowPicture,new InfoWindowRefresher(marker)); } return v; } @Override public View getInfoContents(Marker marker) { return null; } }); 

La callback es bastante simple, como puede ver. Sin embargo, al usar este método, DEBE tener cuidado de usar solo la callback en la primera llamada, y no en llamadas posteriores (simplemente puse esa not_first_time_showing_info_window para reflejar la idea … tendrá que ver cómo incluir eso en su lógica de progtwig. Si no hace eso, la callback de Picasso llamará a showInfoWindow() y eso volverá a llamar a la callback, que recordará showInfoWindow() … bueno, puede ver a dónde va esa recursión. 🙂

Lo principal es conseguir que la carga de Picasso con la callback solo se ejecute una vez, y en las llamadas posteriores, sin la callback.

Resolví este problema usando magia negra (también conocido como establecer un retraso). Aproveché el almacenamiento en caché de Picasso y simplemente llamé a showInfoWindow unos pocos milisegundos después de que comenzara la carga inicial.

Aquí está mi CustomWindowAdapter.

 class CustomWindowAdapter implements InfoWindowAdapter{ LayoutInflater mInflater; Map imageStringMapMarker; Context context; public CustomWindowAdapter(LayoutInflater i, Map imageStringMapMarker2, Context context ){ mInflater = i; imageStringMapMarker = imageStringMapMarker2; } @Override public View getInfoContents(final Marker marker) { View v = mInflater.inflate(R.layout.custom_info_window, null); ImageView ivThumbnail = (ImageView) v.findViewById(R.id.ivThumbnail); String urlImage = imageStringMapMarker.get(marker).toString(); Picasso.with(context).load(Uri.parse(urlImage)).resize(250,250).into(ivThumbnail); return v; } @Override public View getInfoWindow(Marker marker) { // TODO Auto-generated method stub return null; } } 

Y aquí está el método para llamar a la ventana de información en mi actividad principal donde implemente el retraso.

 myMap.setInfoWindowAdapter(new CustomWindowAdapter(this.getLayoutInflater(), imageStringMapMarker, getApplicationContext())); myMap.setOnMarkerClickListener(new OnMarkerClickListener() { @Override public boolean onMarkerClick(final Marker mark) { mark.showInfoWindow(); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mark.showInfoWindow(); } }, 200); return true; } }); 

Cualquier cosa que regrese de getInfoContents() , en ese momento, se convierte en un Bitmap y se usa para mostrar los resultados. No está visualizando la imagen hasta más tarde, cuando la descarga esté completa, momento en el cual ya se creó y se utilizó el Bitmap .

Deberá descargar la imagen antes de getInfoContents() .

Hago esto, también haciendo referencia a la respuesta @ Daniel Gray :

 if (userImg.getDrawable() == null) { Picasso.with(ctx).load(UtilitiesApp.urlServer + user.getImgUrl()) .error(R.drawable.logo) .into(userImg, new InfoWindowRefresher(marker)); } else { Picasso.with(ctx).load(UtilitiesApp.urlServer + user.getImgUrl()) .error(R.drawable.logo) .into(userImg); } public class InfoWindowRefresher implements Callback { private Marker markerToRefresh; public InfoWindowRefresher(Marker markerToRefresh) { this.markerToRefresh = markerToRefresh; } @Override public void onSuccess() { markerToRefresh.showInfoWindow(); } @Override public void onError() {} }