Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

android - Picasso image loading issue in GoogleMap.InfoWindowAdapter

I am using Google Maps Api and want to show an image inside InfoWindow when clicking of a Marker. I implemented it but there is a problem about Picasso. When I click a marker, infoWindow is shown up and imageView shows placeholder image. If I click same marker one more time, Picasso loads the image succesfully. I have to click twice, it is so weird.

Screenshots for better understanding:

First click on the marker:

First Click

When I click again:

Click again

There is my codes below:

InfoWindowAdapter (Picasso loading here)

mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
        @Override
        public View getInfoWindow(Marker marker) {
            return null;
        }

        @Override
        public View getInfoContents(Marker marker) {
            View myContentsView = getLayoutInflater().inflate(R.layout.map_info_content, null);
            ImageView imageView = (ImageView) myContentsView.findViewById(R.id.imgView_map_info_content);
            Picasso.with(MainActivity.this)
                    .load(marker.getSnippet())
                    .placeholder(R.drawable.ic_placeholder)
                    .into(imageView);
            return myContentsView;
        }
    });

Setting markers (using snippet to pass image url)

for (MediaFeedData item : mItemList) {
        LatLng position = new LatLng(item.getLocation().getLatitude(),
                item.getLocation().getLongitude());
        mMap.addMarker(new MarkerOptions()
                .snippet(item.getImages().getLowResolution().getImageUrl())
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_point))
                .position(position));
    }

InfoWindow layout xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ImageView
    android:id="@+id/imgView_map_info_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</LinearLayout>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I solved it. Actually, this post is the answer. But I want to explain how to do it and give more details to solve this problem in my situation.

When showing an InfoWindow, it is captured of the layout. It means that InfoWindows are not dynamic, they are just a picture, a snapshot. That's why, we have to refresh the InfoWindow after image loaded successfully. We can use Picasso's Callback to do it.

I changed my codes like below:

My new InfoWindowAdapter Class:

public class MapInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {
    private final Hashtable<String, Boolean> markerSet;
    private Context context;
    private View myContentsView;

    public MapInfoWindowAdapter(Context context, Hashtable<String, Boolean> markerSet) {
        this.context = context;
        this.markerSet = markerSet;
    }

    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }

    @Override
    public View getInfoContents(Marker marker) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        myContentsView = inflater.inflate(R.layout.map_info_content, null);
        ImageView imageView = (ImageView) myContentsView.findViewById(R.id.imgView_map_info_content);
        boolean isImageLoaded = markerSet.get(marker.getId());
        if (isImageLoaded) {
            Picasso.with(context)
                    .load(marker.getSnippet())
                    .placeholder(R.drawable.ic_placeholder)
                    .into(imageView);
        } else {
            isImageLoaded = true;
            markerSet.put(marker.getId(), isImageLoaded);
            Picasso.with(context)
                    .load(marker.getSnippet())
                    .placeholder(R.drawable.ic_placeholder)
                    .into(imageView, new InfoWindowRefresher(marker));
        }

        return myContentsView;
    }
}

I passed to it a markers set, it holds marker ids and a boolean to determine image for that marker is loaded or not. I am checking this to select which Picasso code should run. If I don't do this, it will be recursion.

InfoWindowRefresher:

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

Setting markers (using snippet to pass image url):

Hashtable<String, Boolean> markerSet = new Hashtable<>();
for (MediaFeedData item : mItemList) {
    LatLng position = new LatLng(item.getLocation().getLatitude(),
            item.getLocation().getLongitude());
    MarkerOptions markerOptions = new MarkerOptions()
            .snippet(item.getImages().getLowResolution().getImageUrl())
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_point))
            .position(position);
    Marker marker = mMap.addMarker(markerOptions);
    markerSet.put(marker.getId(), false);
}

mMap.setInfoWindowAdapter(new MapInfoWindowAdapter(this, markerSet));

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...