Thursday, August 1, 2013

Display Custom Info Window with ImageView on Google Map V2

Display Custom Info Window with ImageView on Google Map V2

 


To display image on Google Map V2 Bubble, we will be integrating Universal Image Loader
In Map V2, to display custom bubble, there is a InfoWindowAdapter class.

Implement the InfoWindowAdapter class and override 2 methods :
1. getInfoContents(Marker marker)
2. getInfoWindow(Marker marker)

Set InfoWindowAdapter
googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
Store Marker id in variable with each marker image URL. So, in CustomInfoWindowAdapter class, it can be accessed using Marker Id. Fro now we will store id in Hashtable:
markers.put(hamburg.getId(), "http://img.india-forums.com/images/100x100/37525-a-still-image-of-akshay-kumar.jpg");
Create custom_info_window.xml layout. It will be displayed when click on Marker.
<?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:background="@drawable/custom_info_bubble"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/badge"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginRight="5dp"
        android:adjustViewBounds="true" >
    </ImageView>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="#ff000000"
            android:textSize="14dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/snippet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff7f7f7f"
            android:textSize="14dp" />
    </LinearLayout>

</LinearLayout>

CustomInfoWindowAdapter 

package com.ngshah.goglemapv2withlazyloading;

import java.util.Hashtable;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.ngshah.goglemapv2withlazyloading.R;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.FIFOLimitedMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;

public class MainActivity extends FragmentActivity {

    private GoogleMap googleMap;
    private final LatLng HAMBURG = new LatLng(53.558, 9.927);
    private final LatLng KIEL = new LatLng(53.551, 9.993);
    private Marker marker;
    private Hashtable<String, String> markers;
    private ImageLoader imageLoader;
    private DisplayImageOptions options;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();
        
        initImageLoader();
        markers = new Hashtable<String, String>();
        imageLoader = ImageLoader.getInstance();
        
        options = new DisplayImageOptions.Builder()
            .showStubImage(R.drawable.ic_launcher)        //    Display Stub Image
            .showImageForEmptyUri(R.drawable.ic_launcher)    //    If Empty image found
            .cacheInMemory()
            .cacheOnDisc().bitmapConfig(Bitmap.Config.RGB_565).build();
        
        if ( googleMap != null ) {
           
            googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
           
            final Marker hamburg = googleMap.addMarker(new MarkerOptions().position(HAMBURG)
                        .title("Hamburg"));
            markers.put(hamburg.getId(), "http://img.india-forums.com/images/100x100/37525-a-still-image-of-akshay-kumar.jpg");
           
            final Marker kiel = googleMap.addMarker(new MarkerOptions()
                        .position(KIEL)
                        .title("Kiel")
                        .snippet("Kiel is cool")
                        .icon(BitmapDescriptorFactory
                            .fromResource(R.drawable.ic_launcher)));
            markers.put(kiel.getId(), "http://www.yodot.com/images/jpeg-images-sm.png");
             
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));
            googleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
        }
    }
    
    private class CustomInfoWindowAdapter implements InfoWindowAdapter {

        private View view;

        public CustomInfoWindowAdapter() {
            view = getLayoutInflater().inflate(R.layout.custom_info_window,
                    null);
        }

        @Override
        public View getInfoContents(Marker marker) {

            if (MainActivity.this.marker != null
                    && MainActivity.this.marker.isInfoWindowShown()) {
                MainActivity.this.marker.hideInfoWindow();
                MainActivity.this.marker.showInfoWindow();
            }
            return null;
        }

        @Override
        public View getInfoWindow(final Marker marker) {
            MainActivity.this.marker = marker;

            String url = null;

            if (marker.getId() != null && markers != null && markers.size() > 0) {
                if ( markers.get(marker.getId()) != null &&
                        markers.get(marker.getId()) != null) {
                    url = markers.get(marker.getId());
                }
            }
            final ImageView image = ((ImageView) view.findViewById(R.id.badge));

            if (url != null && !url.equalsIgnoreCase("null")
                    && !url.equalsIgnoreCase("")) {
                imageLoader.displayImage(url, image, options,
                        new SimpleImageLoadingListener() {
                            @Override
                            public void onLoadingComplete(String imageUri,
                                    View view, Bitmap loadedImage) {
                                super.onLoadingComplete(imageUri, view,
                                        loadedImage);
                                getInfoContents(marker);
                            }
                        });
            } else {
                image.setImageResource(R.drawable.ic_launcher);
            }

            final String title = marker.getTitle();
            final TextView titleUi = ((TextView) view.findViewById(R.id.title));
            if (title != null) {
                titleUi.setText(title);
            } else {
                titleUi.setText("");
            }

            final String snippet = marker.getSnippet();
            final TextView snippetUi = ((TextView) view
                    .findViewById(R.id.snippet));
            if (snippet != null) {
                snippetUi.setText(snippet);
            } else {
                snippetUi.setText("");
            }

            return view;
        }
    }

    private void initImageLoader() {
        int memoryCacheSize;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
            int memClass = ((ActivityManager) 
                    getSystemService(Context.ACTIVITY_SERVICE))
                    .getMemoryClass();
            memoryCacheSize = (memClass / 8) * 1024 * 1024;
        } else {
            memoryCacheSize = 2 * 1024 * 1024;
        }

        final ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                this).threadPoolSize(5)
                .threadPriority(Thread.NORM_PRIORITY - 2)
                .memoryCacheSize(memoryCacheSize)
                .memoryCache(new FIFOLimitedMemoryCache(memoryCacheSize-1000000))
                .denyCacheImageMultipleSizesInMemory()
                .discCacheFileNameGenerator(new Md5FileNameGenerator())
                .tasksProcessingOrder(QueueProcessingType.LIFO).enableLogging() 
                .build();

        ImageLoader.getInstance().init(config);
    }
} 

22 comments:

  1. Nishant, thanks for this great example! But I have one question: imagine I would like to make my info window exactly the same as the original, and the only thing I would like to change is its background color and opacity. Do you think there would be a simpler way to do that?

    ReplyDelete
  2. Hello Nishant ,
    Perfect example .
    But i want to set googleMap.addMarker(new MarkerOptions().icon using Lazy loading .

    Thanks
    Parag

    ReplyDelete
  3. Hello Nishant, Thanks for your sharing.
    This is very helpful for me.

    Thanks!

    ReplyDelete
  4. Nice tutorial..pls add the date when it is posted... :)

    ReplyDelete
  5. Flat in Yamuna Expressway
    :-we are happy to read your post , its a very nice and more informative...

    ReplyDelete
  6. Thanks for solution... Point is that on UniversalImageLoader and onLoadingComplete(), call getInfoContents(marker) and after it calls rerun infoWindow with loaded image... :)

    ReplyDelete
  7. getInfoWindow() -> onLoadingComplete() -> getInfoContents(marker). This call comes in loop as showInfoWindow() again call getInfoWindow. This increases memory consumption and GC get called continuously.

    instaead of calling getInfoContents(marker) explicitly, image.setImageBitmap(loadedImage) will work perfect.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  8. Last month, the California-based internet giant began re-evaluating its user-edited online map system after the latest embarrassing incident -- an image of an Android mascot urinating on an Apple logo. To know more about , Visit Android training in chennai

    ReplyDelete
  9. hi is there any way to get data in info window at multiple marker different data load from list

    ReplyDelete
  10. Hi!
    Thanks for your sharing,

    But I have problem in code:

    markers.put(hamburg.getId(), "http://img.india-forums.com/images/100x100/37525-a-still-image-of-akshay-kumar.jpg");

    I want picture url is a SDcard url...How do I change code?

    Thanks for all the help!

    ReplyDelete
  11. @drawable/custom_info_bubble is missing

    ReplyDelete
  12. Hi
    Thanks for sharing your code but i have a problem with onclick on textview in infowindow,Is it possible to make textview as a clickable in Infowindow?

    ReplyDelete
  13. I just see the post i am so happy to the communication science post of information's.So I have really enjoyed and reading your blogs for these posts.Any way I’ll be replay for your great thinks and I hope you post again soon.

    digital marketing company in india

    ReplyDelete
  14. This post is really nice and informative. The explanation given is really comprehensive and informative.. android Training in Chennai

    ReplyDelete
  15. I am very much pleased with the contents you have mentioned. I wanted to thank you for this great article. I enjoyed every little bit part of it and I will be waiting for the new updates.
    custom logo

    ReplyDelete
  16. It's interesting that many of the bloggers to helped clarify a few things for me as well as giving.Most of ideas can be nice content.The people to give them a good shake to get your point and across the command .
    Pest Control in Chennai

    ReplyDelete
  17. Great post! I am actually getting ready to across this information, It's very helpful for this blog.Also great with all of the valuable information you have Keep up the good work you are doing well.

    Digital Marketing Company in Chennai

    ReplyDelete
  18. I am not sure the place you are getting your information, however good topic.I needs to spend some time studying more or understanding more.Thank you for wonderful information I was in search of this info for my mission.

    HR Consultancy in Chennai
    Recruitment Consultancy in Chennai
    Manpower Consultancy in Chennai

    ReplyDelete
  19. This information is impressive; I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this, I feel happy about it and I love learning more about this topic.Android Training institute in chennai with placement | Best Android Training in velachery

    ReplyDelete