Добавьте изображение с url в пользовательские InfoWindow google maps v2

Я работаю в приложении для Android. Пользователь выполняет поиск на картах google для ресторанов. В марке google map отображаются маркеры для всего ресторана его соседа. Если он нажат на маркер, он отобразит пользовательский InfoWindow. Моя проблема в том, что я не могу загрузить образ, возвращающийся из Google. Я получаю правильный URL-адрес изображения, но я не могу показать его в окне.

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> 

На создание у меня это

 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; } 

});

И код DownloadImage:

 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(); } } } 

Наконец, когда я выполняю код и нажимаю маркер, getInfoContents не прекращает выполнение, и значок не появляется.

У кого-нибудь есть идея, почему это происходит? Пожалуйста, помогите мне …. Спасибо в advace !!

Solutions Collecting From Web of "Добавьте изображение с url в пользовательские InfoWindow google maps v2"

Я создал подобное приложение.

Прежде всего, причина, по которой ваш InfoWindow не показывает загруженное изображение, заключается в том, что MapFragment отображает представление в Canvas , а затем рисует это. То, что вы видите в информационном окне, – это не созданные вами виды, а «фотография» или «скриншот». Вам в основном нужно снова вызвать showInfoWindow() в объекте Marker , и это будет повторно отображать Canvas и ваше изображение теперь будет видимым.

Тем не менее, при этом, по моему опыту, загрузка Bitmap из URL-адреса, а затем настройка это не лучшее решение. Android не очень хорошо обрабатывает Bitmap . После загрузки нескольких растровых изображений исключение OutOfMemoryError – это всего лишь вопрос времени, в зависимости от объема вашей системной памяти.

Я бы рекомендовал использовать библиотеку Picasso, которая обрабатывает асинхронную загрузку и кеширование (в памяти и на диске) и делает фактическую загрузку изображения только одной строкой ( Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); ). (Больше информации на http://square.github.io/picasso/ )

Предыдущий ответ был хорошим, за исключением того, что, по его словам, эта «задержка» немного волшебна для моего вкуса. У Picasso есть возможность использовать обратные вызовы, и я бы рекомендовал использовать это (я использую это в своем приложении).

Сначала создайте класс (он может быть внутренним для вашей активности), который реализует интерфейс Callback Picasso и получает Marker в конструкторе (так что вы можете showInfoWindow() вызвать showInfoWindow() на этом маркере.

 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() {} } 

Информационное окно выглядит следующим образом:

 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; } }); 

Обратный вызов довольно прост, как вы можете видеть. Однако при использовании этого метода вы ДОЛЖНЫ быть осторожны, чтобы использовать обратный вызов только при первом вызове, а не в последующих вызовах (я просто ввел это not_first_time_showing_info_window чтобы отразить идею … вам нужно будет увидеть, как включить это в Ваша программная логика. Если вы этого не сделаете, обратный вызов Picasso вызовет showInfoWindow() и он повторно вызовет обратный вызов, который будет напоминать showInfoWindow() … ну, вы можете видеть, куда идет эта рекурсия. 🙂

Главное – загрузить нагрузку Picasso с обратным вызовом только один раз и последующие вызовы без обратного вызова.

Я решил эту проблему, используя черную магию (ака задержка). Я воспользовался кэшированием Пикассо и просто вызвал showInfoWindow через несколько миллисекунд после начала начальной загрузки.

Вот мой 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; } } 

И вот метод вызова информационного окна в моей основной деятельности, где я реализую задержку.

 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; } }); 

Независимо от getInfoContents() , что вы getInfoContents() из getInfoContents() , в этот момент преобразуется в Bitmap и используется для отображения результатов. Вы не показываете изображение до тех пор, пока загрузка не будет завершена, и к какой точке времени Bitmap уже создан и используется.

Вам нужно будет загрузить изображение перед getInfoContents() .

Я делаю это, также ссылаясь на @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() {} }