Androidアプリで作業しています。ユーザーはGoogleマップでレストランを検索します。Googleマップでは、隣人のすべてのレストランのマーカーを表示します。マーカーをタップすると表示されますカスタムInfoWindowを作成します。私の問題は、Googleの場所から返される画像を読み込めないことです。画像のURLを正しく取得できましたが、Windowに表示できません。
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が実行を停止せず、アイコンが表示されません。
なぜこれが起こるのですか?
同様のアプリを作成しています。
まず、InfoWindowにダウンロードした画像が表示されないのは、MapFragment
がビューをCanvas
にレンダリングしてから描画するためです。情報ウィンドウに表示されるのは、作成したビューではなく、それらの「画像」または「スクリーンショット」です。基本的に、Marker
オブジェクトでshowInfoWindow()
を再度呼び出す必要があります。これにより、Canvas
が再レンダリングされ、画像が表示されます。
ただし、そうは言っても、私の経験では、URLからBitmap
を読み込んで設定することは最善の解決策ではありません。 AndroidはBitmap
sをうまく処理しません。いくつかのビットマップをロードした後、システムメモリの量に応じて、OutOfMemoryError
例外は時間の問題ですあなたが持っている。
非同期ダウンロードとキャッシュ(メモリとディスク内)を処理し、実際のイメージの読み込みを1行だけにする(Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
)ピカソライブラリの使用をお勧めします。 (詳細は http://square.github.io/picasso/ にあります)
前の答えは良かったが、彼が言ったように、「遅延」は私の好みには少し不思議すぎる。ピカソにはコールバックを使用するオプションがあり、それを使用することをお勧めします(私はそれをアプリで使用しています)。
まず、ピカソの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;
}
});
_
ご覧のとおり、コールバックは非常に単純です。ただし、この方法を使用するときは、最初の呼び出しでのみコールバックを使用し、後続の呼び出しでは使用しないように注意する必要があります(私は単に_not_first_time_showing_info_window
_アイデアを反映するには...それをプログラムロジックに含める方法を確認する必要があります。そうしないと、PicassoコールバックがshowInfoWindow()
を呼び出し、それが再実行されます-showInfoWindow()
...をリコールするコールバックを呼び出します。
主なことは、コールバックを使用してピカソのロードを1回だけ実行し、その後の呼び出しではコールバックなしで実行することです。
私はこの問題をブラックマジック(別名、遅延の設定)を使用して解決しました。私はピカソのキャッシュを利用して、最初の読み込みが始まってから数ミリ秒後に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
が既に作成および使用されている時点で、ダウンロードが完了するまで、イメージは表示されません。
getInfoContents()
が呼び出される前に、イメージをダウンロードする必要があります。
@ Daniel Grey answer も参照してこれを行います。
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() {}
}