从url添加一个图像到自定义InfoWindow谷歌地图V2

我正在一个Android应用程序工作。 用户在谷歌地图上search餐馆。 在谷歌地图显示标记为他所有的邻居的餐厅。 如果他点击一个标记,它会显示一个自定义的InfoWindow。 我的问题是,我无法加载Google放置的图片。 我正确的图像的url,但我不能在窗口显示。

信息窗口

<?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> 

在创build我有这个

 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不会停止执行,并且图标不会出现。

为什么会发生?

Solutions Collecting From Web of "从url添加一个图像到自定义InfoWindow谷歌地图V2"

我一直在build立一个类似的应用程序。

首先,你的InfoWindow没有显示下载的图像的原因是因为MapFragment将视图渲染成一个Canvas ,然后绘制它。 您在信息窗口中看到的不是您创build的视图,而是它们的“图片”或“屏幕截图”。 您基本上需要再次调用Marker对象上的showInfoWindow() ,这将重新呈现Canvas ,您的图像现在将可见。

然而,这就是说,以我的经验从URL加载Bitmap ,然后设置它不是最好的解决scheme。 Android不能很好地处理Bitmap 。 加载几个位图后, OutOfMemoryErrorexception只是一个时间问题,具体取决于系统内存的数量。

我build议使用Picasso库,它处理asynchronous下载和caching(在内存和磁盘),并使实际图像加载只有一行( Picasso.with(context).load("http://sofzh.miximages.com/android/DvpvklR.jpg").into(imageView); )。 (更多信息在http://square.github.io/picasso/

以前的答案是好的,只是如他所说,“延迟”对我来说有点太神奇了。 毕加索有使用callback的选项,我build议使用(我在我的应用程序中使用)。

首先创build一个实现毕加索Callback接口的类(它可以是内部的),并在构造函数中接收一个Marker (所以你可以再次调用该标记的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; } }); 

callback很简单,就像你看到的那样。 然而,使用这种方法时,你必须小心只在第一次调用中使用callback,而不是在随后的调用中(我只是在not_first_time_showing_info_window中反映这个想法…你将不得不看看如何包含你的程序逻辑如果你不这样做,毕加索callback将调用showInfoWindow() ,并将重新调用callback,这将callbackshowInfoWindow() …以及,你可以看到recursion的showInfoWindow()

最重要的是让毕加索加载callback只运行一次,并在随后的调用,没有callback。

我用黑魔法(也就是设置延迟)解决了这个问题。 我利用毕加索的caching,并在初始加载开始后的几毫秒内调用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()返回,此时都将转换为Bitmap ,并用于显示结果。 直到以后,当下载完成时,才显示图像,此时Bitmap已经创build并使用。

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