Friday 8 January 2010

Android - Baloon Display On Map

I see several posts in Android forums about people asking how to display baloon structures on mapviews. In one of my draft applications I declare a simple solution for this (for source codes and any other issues related to this post, feel free to write me at serkan.dogantekin@gmail.com):

- Define a layout for baloon structure and its "dispatchDraw" draw the baloon itself like:

package com.dogantekin.baloon;

public class BaloonLayout extends LinearLayout {

    .......

    @Override
    protected void dispatchDraw(Canvas canvas) {       
        Paint panelPaint  = new Paint();
        panelPaint.setARGB(0, 0, 0, 0);
               
        RectF panelRect = new RectF();
        panelRect.set(0,0, getMeasuredWidth(), getMeasuredHeight());
        canvas.drawRoundRect(panelRect, 5, 5, panelPaint);
       
        RectF baloonRect = new RectF();
        baloonRect.set(0,0, getMeasuredWidth(), 2*(getMeasuredHeight()/3));
        panelPaint.setARGB(230, 255, 255, 255);       
        canvas.drawRoundRect(baloonRect, 10, 10, panelPaint);
       
        Path baloonTip = new Path();
        baloonTip.moveTo(5*(getMeasuredWidth()/8), 2*(getMeasuredHeight()/3));
        baloonTip.lineTo(getMeasuredWidth()/2, getMeasuredHeight());
        baloonTip.lineTo(3*(getMeasuredWidth()/4), 2*(getMeasuredHeight()/3));
       
        canvas.drawPath(baloonTip, panelPaint);
               
        super.dispatchDraw(canvas);
    }

}

- Define a layout xml for this layout and add views that will be inside this layout like:

<?xml version="1.0" encoding="utf-8"?>
<com.dogantekin.baloon.BaloonLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/transparent_panel"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="5px"
    android:paddingTop="5px"
    android:paddingRight="5px"
    android:paddingBottom="5px">
    <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content">
        <TextView
            android:id="@+id/note_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:text="@string/note"
        />
        <ImageView
            android:id="@+id/close_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:paddingRight="10px"       
            android:src="@drawable/close"
            android:clickable="true"
        />
        <TextView
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:paddingLeft="5px"
            android:paddingRight="5px"
            android:text=""
            android:id="@+id/note_text"
            android:layout_below="@+id/note_label"
            android:layout_centerHorizontal="true"
            android:minLines="4"
            android:maxLines="4"
            android:maxLength="160"   
            android:textSize="5pt"   
        />
    </RelativeLayout>
</com.dogantekin.baloon.BaloonLayout>

- In your map activity (where you will have your mapview) create an instance of layout we defined:


        LayoutInflater              layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        noteBaloon = (BaloonLayout) layoutInflater.inflate(R.layout.baloon, null);
        RelativeLayout.LayoutParams layoutParams   = new RelativeLayout.LayoutParams(200,100);
        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
        layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        noteBaloon.setLayoutParams(layoutParams);   


- Now whenever you need to display the baloon, just call mapview's addView method as:

mapView.removeView(noteBaloon);
noteBaloon.setVisibility(View.VISIBLE);
                     ((TextView)noteBaloon.findViewById(R.id.note_text)).setText(msg.getData().getString(HANDLER_MESSAGE_AUTHOR)+"\n"+msg.getData().getString(HANDLER_MESSAGE_NOTE));

mapController.animateTo(noteOverlay.getTapPoint());
mapView.addView(noteBaloon, new MapView.LayoutParams(200,200,noteOverlay.getTapPoint(),MapView.LayoutParams.BOTTOM_CENTER));
mapView.setEnabled(false);       
 

- When  you need to remove baloon, just make it invisible:

noteBaloon.setVisibility(View.GONE);                    
mapView.setEnabled(true);     



Below you can find how it is looking:
  • initial mapview

















  • just make a tap

















  • touch the close image on baloon

  • insert new items in layout xml for richer baloon displays




Reblog this post [with Zemanta]

83 comments:

  1. Any chance you could provide the full working source code? Im getting a LayoutInflater error - not sure what that means... Thanks!

    ReplyDelete
  2. Just send me an email (serkan.dogantekin@gmail.com), and I will send you a sample project

    ReplyDelete
  3. Hi Serkan, could you also send me the sample project please (mathias.conradt@gmail.com).

    I also get an exception like Becca:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myproject.android/com.myproject.android.activity.map.Map}: android.view.InflateException: Binary XML file line #2: Error inflating class com.myproject.android.activity.map.BalloonLayout

    Thanks.

    ReplyDelete
  4. Very nice tutorial. Exactly what I was looking for.

    I used your example and now I am able to show the balloons over the overlay items with the appropriate text. But I seem to have a problem attaching a listener to the clickable ImageView in the BaloonLayout.

    Here is what I tried in the onCreate of the MapActivity:

    LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    noteBaloon = (BaloonLayout) layoutInflater.inflate(R.layout.baloon, null);
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200,100);
    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
    layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
    noteBaloon.setLayoutParams(layoutParams);

    // Get the clickable TextView
    TextView buttonView = (TextView) findViewById(R.id.close_button);
    // THE FOLLOWING LINE THROWS AN EXCEPTION
    buttonView.setOnClickListener(new OnClickListener()
    {
    public void onClick(View v)
    {
    // Do something on click
    }
    });

    This code throws java.lang.NullPointerException on the line that adds the onClickListener to the buttonView.

    Any help is greatly appreciated.

    Thank you in advance.

    ReplyDelete
  5. I must have been pretty tired last night :-(

    I did overlook an essential detail. I forgot to put buttonView.findViewById instead of just findViewById, because the the view object is not in the default xml layout file of the activity, rather is is in the BaloonLayout that we inflated from R.layout.baloon in the code above.

    Here is what you should do:

    buttonView = (ImageView) noteBaloon.findViewById(R.id.close_button);

    ReplyDelete
  6. Please also send me the complete code to sasi.vemuri@gmail.com

    ReplyDelete
  7. Hi,

    Please send me the complete code to s.work.info@gmail.com,i'm in need pls.

    ReplyDelete
  8. Awesome!
    Just what I was looking for. Thanks

    ReplyDelete
  9. Hi, Please send me the complete code to:

    mohamedneptune2050@gmail.com

    Thanks

    ReplyDelete
  10. Hi

    please anyone send me the code to nando.velazquez@gmail.com, i need it!

    thnx

    ReplyDelete
  11. Hi, I really need the code too.
    outedata@gmail.com Thank you really very very much!!!

    ReplyDelete
  12. public class Ballon extends MapActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    MapView mapView = (MapView) findViewById(R.id.mapView);
    mapView.setBuiltInZoomControls(true);
    List mapOverlays = mapView.getOverlays();
    Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker);
    ItemizedOverlayContainer itemized = new ItemizedOverlayContainer(drawable);
    GeoPoint point = new GeoPoint((new Double(52.000*1E6).intValue()),
    (new Double(11.000*1E6).intValue()));
    OverlayItem item = new OverlayItem(point,"","");
    itemized.addOverlay(item);
    mapOverlays.add(itemized);

    MapController mapController = mapView.getController();




    LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    Buble noteBaloon = (Buble) layoutInflater.inflate(R.layout.ballon, null);


    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200,100);
    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
    layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
    noteBaloon.setLayoutParams(layoutParams);

    mapView.removeView(noteBaloon);
    noteBaloon.setVisibility(View.VISIBLE);
    // TextView textmsg = (TextView) noteBaloon.findViewById(R.id.note_text);
    TextView textmsg = (TextView) noteBaloon.findViewById(R.id.note_text);
    textmsg.setText("I am a Popup Balloon!!!");
    mapView.addView(noteBaloon, new MapView.LayoutParams(200,200,item.getPoint(),MapView.LayoutParams.BOTTOM_CENTER));
    mapView.setEnabled(false);
    }

    @Override
    protected boolean isRouteDisplayed() {
    // TODO Auto-generated method stub
    return false;
    }
    }

    public class Buble extends LinearLayout {



    public Buble(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
    Paint panelPaint = new Paint();
    panelPaint.setARGB(0, 0, 0, 0);

    RectF panelRect = new RectF();
    panelRect.set(0,0, getMeasuredWidth(), getMeasuredHeight());
    canvas.drawRoundRect(panelRect, 5, 5, panelPaint);

    RectF baloonRect = new RectF();
    baloonRect.set(0,0, getMeasuredWidth(), 2*(getMeasuredHeight()/3));
    panelPaint.setARGB(230, 255, 255, 255);
    canvas.drawRoundRect(baloonRect, 10, 10, panelPaint);

    Path baloonTip = new Path();
    baloonTip.moveTo(5*(getMeasuredWidth()/8), 2*(getMeasuredHeight()/3));
    baloonTip.lineTo(getMeasuredWidth()/2, getMeasuredHeight());
    baloonTip.lineTo(3*(getMeasuredWidth()/4), 2*(getMeasuredHeight()/3));

    canvas.drawPath(baloonTip, panelPaint);

    super.dispatchDraw(canvas);
    }
    }
    public class ItemizedOverlayContainer extends ItemizedOverlay{

    private ArrayList mOverlays = new ArrayList();

    public ItemizedOverlayContainer(Drawable defaultMarker) {
    super(boundCenterBottom(defaultMarker));
    }

    @Override
    public int size() {
    return mOverlays.size();
    }

    public void addOverlay(OverlayItem overlay) {
    mOverlays.add(overlay);
    populate();
    }
    @Override
    protected OverlayItem createItem(int i) {
    return mOverlays.get(i);
    }

    }

    ReplyDelete
    Replies
    1. i am getting a class cast exception in this line, can you kindly tell me why is it?

      Buble noteBaloon = (Buble) layoutInflater.inflate(R.layout.ballon, null);

      Delete
  13. Hey!

    can anyone send me the code please? I just can't figure how to do it...
    my email: d.breucker@gmail.com

    Thanks!

    ReplyDelete
  14. any source code: ? michletic@yahoo.com

    ReplyDelete
  15. Please send me the code to minddol@gmail.com

    ReplyDelete
  16. can someone please send me the code also?

    bob@smartwhere.com

    Thank you

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. could someone send me the full code please? Thanks...
    donatello.indino@gmail.com

    ReplyDelete
  19. can anyone send me the source? Thanks.
    touchaponk@gmail.com

    ReplyDelete
  20. could someone send me the full code please? Thanks...
    brmenninga@gmail.com

    ReplyDelete
  21. could someone send me the full code please? Thanks...
    wp19831014@gmail.com

    ReplyDelete
  22. It will be helpful if some one send me the source code for the same
    gujar.dwarkesh@gmail.com

    ReplyDelete
  23. can anyone send me the code too? It would be very helpful for me... many many thanks... boris.hasselmanngmail.com

    ReplyDelete
  24. sorry i forgot the "@" boris.hasselmann@gmail.com

    ReplyDelete
  25. can anyone send me the full source? Thanks.
    badrulian@hotmail.com

    ReplyDelete
  26. hi
    please send me the source code at ajmersingh09@gmail.com

    ReplyDelete
  27. Please send me the code to ccssby@naver.com

    ReplyDelete
  28. Please send me the code at pichdude@gmail.com. Thanks in advance.

    ReplyDelete
  29. was quite complex tutorial and incomplete too but i have implemented it successfully thanks for the idea. :)
    mr_muskurahat@yahoo.com

    ReplyDelete
    Replies
    1. please mail me the sample code at gansubhai@rediffmail.com

      Delete
  30. great tutorial.

    please can I ve the code to fala70 at gmail dot com

    thanks

    ReplyDelete
  31. Very good tutorial it is what I'm looking for. Would you please send me the code?
    Thank you.
    accretiondisk0620@yahoo.com

    ReplyDelete
  32. Very useful tutorial.
    Could you plz send me the code?
    tunyarat.me@gmail.com

    Thank you so much.

    ReplyDelete
  33. Thanks for the tutorial... can you send me the code?

    julioz92@gmail.com

    ReplyDelete
  34. Nice Tutorial ...can you send me the code?
    My EMail Id is

    tushaarv@gmail.com

    ReplyDelete
  35. I would appreciate if you could send me the source code of this tutorial. my email is mh.mh1008@gmail.com

    Thanks in advance

    ReplyDelete
  36. If I could grab the full source that would be much appreciated :D

    rev.tyler.misc@gmail.com

    ReplyDelete
  37. This comment has been removed by the author.

    ReplyDelete
  38. hey plzzz mail me the code..i need it to implement my final year project..thanks

    chetanbisht11@gmail.com

    ReplyDelete
  39. Please send me the sample code as well.

    my Email is spirulina17@yahoo.coom

    Thanks

    ReplyDelete
  40. Please send me the code too, my email address is:
    michael@rushmobile.hk

    ReplyDelete
  41. Please send me the code too, my email address is:
    jacek.gebala@google.com

    ReplyDelete
  42. Thanks for the tutorial...Can someone please send me the code?

    My Mail ( kennet.rasmussen@gmail.com )

    \\kennet

    ReplyDelete
  43. This comment has been removed by the author.

    ReplyDelete
  44. Can you any one send complete code.My id is
    dennisntstar@gmail.com .

    ReplyDelete
  45. Hello can you send me please code? =(
    to cybot@itelcel.com

    ReplyDelete
  46. Please send me the code at mrprateekjain@gmail.com

    ReplyDelete
  47. please send me the full src code ,thank you zound617@gmail.com

    ReplyDelete
  48. Please send me the code example!!
    mciminieri {at} gmail.com

    ReplyDelete
  49. hi, Please also send me the code sample,
    my id is trkhan88@gmail.com
    thanks in advance :)

    ReplyDelete
  50. Please also send me the code sample.
    jason.yokota@gmail.com
    Thanks!

    ReplyDelete
  51. Nice Post!! Please send me the code... Thanks
    duarteledo@gmail.com

    ReplyDelete
  52. sorry for digging this up, but could u send me your code for this one on dr.mefist@gmail.com ? Thanks in advance

    ReplyDelete
  53. damn, my mistake

    could u send it to dr.mefisto@gmail.com , bloody spelling

    ReplyDelete
  54. could you send me your source code to darklight.kampus@gmail.com
    i'm stuck with android issues error... this baloon driving me crazy

    ReplyDelete
  55. Please send me the full source code at phanquocthinh@gmail.com. Thank you!

    ReplyDelete
  56. Hi,
    Amazing tutorial..Can some one send me source code..email id: deccanblu@yahoo.co.in

    ReplyDelete
  57. plz send me code salahjr@gmail.com .. thaks in advance

    ReplyDelete
  58. Please send full source code to jweg29@gmail.com. Thanks!!

    ReplyDelete
  59. The same request: I would greatly appreciate if you send me the complete source code. Thank you in advance. My email is alukatski@gmail.com

    ReplyDelete
  60. please send me the code at shamoel.hussain@gmail.com..layout is not gettn inflated..:-(

    ReplyDelete
  61. This comment has been removed by the author.

    ReplyDelete
  62. @shamoel: Think you need to add all the default constructors to the BaloonLayout, but even then I'm running into NullPointerExceptions..

    Btw, to anyone that''s not getting this to work, there's a more optimized version that was posted on StackOverflow: http://stackoverflow.com/questions/3707923/show-popup-above-map-marker-in-mapview

    ReplyDelete
  63. can anyone send me the complete sourcecode?
    s161703@stud.hioa.no

    ReplyDelete
  64. can any please send me working sourcecode at imam.anwar@gmail.com.
    Thanx in advance.

    ReplyDelete
  65. Can you please send me the working source code on nela_st@yahoo.com?
    Please, I've been stuck at this for days now and I need it soon!

    ReplyDelete
  66. Hi, Its a very nice Tutorial. Can you please kindly send me the sample code of this on keyuraashra@gmail.com

    Thanks

    ReplyDelete
  67. Could you send me the code please ?

    stangabogdan96@gmail.com

    ReplyDelete
  68. Hello
    Nice Tutorial.. Plz Send Me The Code Thanks !
    med.sahliano@gmail.com

    ReplyDelete
  69. please send me the complete code to me.

    jithups59@gmail.com

    ReplyDelete
  70. Hi,
    Please send me the complete source code or sample project.
    hlaingwintunn@gmail.com

    ReplyDelete
  71. Hi,
    Please send me the complete source code or sample project.
    pavan@mojostreet.com

    ReplyDelete
  72. hi,
    I have an error to use this code.I use offline tiles map not Google map.So ,I face the error.my error is

    MapView.LayoutParams(200,200,item.getPoint(),MapView.LayoutParams.BOTTOM_CENTER));

    I want to display the information with baloon box onto for my mapView.

    how do I use for my offline map(map.sqlitedb)?
    Please Help me.
    hlaingwintunn@gmail.com

    ReplyDelete
  73. hi please send me the source code at soni.akhil06@gmail.com


    Thanks

    ReplyDelete
  74. hi could you send me the working code of this example to pavan@mojostreet.com

    Thanks

    ReplyDelete
  75. Can send me the working codes too? send it at nur_fiza_haron@hotmail.com

    ReplyDelete
  76. Please send me a full working code in my e-mail at mail.suvankar@gmail.com

    ReplyDelete
  77. If someone has got the source code plz email me.. sowmyasguru@gmail.com

    ReplyDelete
  78. Please send me a full version of work in to my e-mail --> am.methinee@gmail.com
    Please help me I have to use it within this week
    Thank you

    ReplyDelete
  79. Hai all...pls send code to sel.ajaykumar@gmail.com

    ReplyDelete
  80. Hi,
    please send me a code to --->pansuriyasumit@gmail.com
    Thanks.

    ReplyDelete