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]