Agregar una imagen de url a InfoWindow personalizado google maps v2
Estoy trabajando en una aplicación para Android. El usuario realiza una búsqueda en google maps para restaurantes. En google mapa marcadores de pantalla para todo el restaurante de su vecino. Si toca en un marcador, aparece una InfoWindow personalizada. Mi problema es que no puedo cargar la imagen que devuelve los lugares de Google forma. Im consiguiendo derecho el URL de la imagen pero no puedo demostrarla en la ventana.
InfoWindow
- Google Maps Android API v2 - Interactive InfoWindow (como en los mapas originales de google google)
- Google Maps v2 android, ventana de información no se destacan en el color de resaltado por defecto en el clic?
- Cambiar o quitar completamente el color de resaltado de un InfoWindow de Google Maps v2 en Android
- Cambiar el color del margen de la vista InfoWindow del marcador en google maps api v2
- android marker custom infowindow
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:background="@color/bg_color" > <ImageView android:id="@+id/place_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false"" /> <TextView android:id="@+id/place_title" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/place_vicinity" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@color/bg_color" > <RatingBar android:id="@+id/place_rating" style="?android:attr/ratingBarStyleSmall" android:numStars="5" android:rating="0" android:isIndicator="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" /> <ImageView android:id="@+id/navigate_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" android:src="@drawable/navigate" /> </LinearLayout>
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 de DownloadImage es:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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 el getInfoContents no deja de ejecutar y el icono no aparece.
¿Alguien tiene alguna idea, ¿por qué sucede esto? Por favor, ayúdame …. Gracias en advace !!
- Cómo desplazarse ventanas de información en el mapa v2?
- Contenido dinámico en Maps V2 InfoWindow
- Cómo descartar una ventana de información en android Google mapa API v2
- Cómo personalizar el color state_pressed de un infowindow en Google Maps?
- Apertura de InfoWindow automáticamente al agregar marcador Google Maps v2 Android
- Cómo agregar la ventana de información para el marcador de clustering en android?
- Crear una ventana de información personalizada en Google Maps V2
- Cómo hacer que el contenido de la ventana de información del marcador haga clic en android
He estado construyendo una aplicación similar.
En primer lugar, la razón por la que su InfoWindow no está mostrando la imagen descargada es porque el MapFragment
hace que la vista en un Canvas
, y luego dibuja eso. 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, es necesario llamar a showInfoWindow()
nuevo en el objeto Marker
, y que volverá a representar el Canvas
y su imagen ahora será visible.
Sin embargo, dicho esto, en mi experiencia cargando el Bitmap
de Bitmap
de la URL y luego la configuración no es la mejor solución. Android no maneja muy bien Bitmap
s. Después de cargar varios mapas de bits, una excepción OutOfMemoryError
es sólo cuestión de tiempo, dependiendo de la cantidad de memoria del sistema que tenga.
Recomiendo usar la biblioteca de Picasso, que maneja la descarga asíncrona, y el almacenamiento en caché (en la memoria y el disco) y hace que la imagen real cargando sólo una línea ( Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
). (más información en http://square.github.io/picasso/ )
La respuesta anterior fue buena, excepto que, como él dijo, ese "retraso" es un poco demasiado mágico para mi gusto. Picasso tiene la opción de usar devoluciones de llamada, y yo recomendaría usar eso (estoy usando eso en mi aplicación).
Primero cree una clase (puede ser interna a su actividad) que implemente la interfaz de Callback
de Picasso y reciba un Marker
en el constructor (para que pueda showInfoWindow()
llamar a showInfoWindow()
en ese marcador.
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 devolución de llamada es bastante simple, como se puede ver. Sin embargo, al usar este método DEBE tener cuidado de utilizar sólo la devolución de llamada en la primera llamada, y no en las llamadas posteriores (Acabo de poner en que not_first_time_showing_info_window
para reflejar la idea … usted tendrá que ver cómo incluir que en la lógica del programa.Si no lo hace, la devolución de llamada de Picasso llamará showInfoWindow()
y que volverá a llamar a la devolución de llamada, que se recordará showInfoWindow()
… bien, usted puede ver donde se está recursión.
Lo principal es conseguir que la carga de Picasso con la devolución de llamada para ejecutar sólo una vez, y en las llamadas siguientes, sin la devolución de llamada.
He resuelto este problema usando magia negra (aka establecer un retraso). Aproveché el almacenamiento en caché de Picasso y acabo de llamar showInfoWindow unos milisegundos después de que comenzara la carga inicial.
Aquí está mi CustomWindowAdapter.
class CustomWindowAdapter implements InfoWindowAdapter{ LayoutInflater mInflater; Map<Marker, String> imageStringMapMarker; Context context; public CustomWindowAdapter(LayoutInflater i, Map<Marker, String> 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 implemento 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; } });
Sea lo que sea que getInfoContents()
de getInfoContents()
, en ese momento, se convierte en un Bitmap
y se utiliza para mostrar los resultados. No mostrará la imagen hasta más tarde, cuando se haya completado la descarga, momento en el que el Bitmap
ya está creado y utilizado.
Usted tendrá que descargar la imagen antes de getInfoContents()
ha sido llamado.
Hago esto, también haciendo referencia a la respuesta de @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() {} }
- Cómo configurar el diseño personalizado para PreferenceActivity en Android 3.0?
- CursorTreeAdapter con implementación de búsqueda