actionshrimp.com

fun and geekery

12  05 2011

Speech Bubble Popups containing a View for Android MapView

Posted by Dave | Tags: , , , , , ,

Update May 2012: There have been lots of requests in the comments for the source. Sorry for the delay on this one – I finally put the whole app that I’d been working on up on github. The part from this tutorial specifically is here if you want to take a look.

I’ve recently been playing around with Android, and have been building a small app that uses MapView to display various locations on the map. I succeeded in drawing markers on the MapView using ItemizedOverlay, but was having a fair bit of difficulty drawing little bubble popups that appeared when you tapped on the OverlayItems (which unfortunately isn’t available in the API as a ‘standard’ feature).

My main problem was I wanted to be able to draw a full View on top of the map at the right location. I had a good old search on Google for a while, and couldn’t seem to find any easy way to do this, so I thought I’d write up how I ended up with the bubble in the screenshot. (Now I know how it’s done however, the Google results seem a lot more knowledgeable on the subject – I was probably searching for the wrong things :-( ).

My first approach was to build a subclass of Overlay and override its draw() method, where I converted the View to a Drawable to draw it directly onto the MapView canvas (passed to draw() ). This worked, but naturally events would no longer work properly in the View if it contained things like buttons, so it was back to the drawing board.

Next, I tried subclassing Dialog, and used a custom Dialog theme with my bubble background. The View I wanted was just injected into the Dialog through its setContentView method. This worked again, but I found myself fighting with the Dialog class a fair bit, and positioning it turned out to be a bit fiddly – there had to be a better way.

Finally I noticed that MapView inherits from the Android ViewGroup, which means it can contain other Views. After a bit more probing, and a peek at the implementation of android-mapviewballoons (which is excellent, but didn’t quite fit my purposes due to lack of custom balloon layouts) found a way to do it which should probably have been obvious from the outset!

The general approach is to add a new child View to the MapView, and then use the MapView.LayoutParams to position it. Here’s a quick outline example if you’re unfamiliar (the View I’m displaying has a NinePatch as the background attribute of a top level LinearLayout, which makes the bubble wrap the content):

This is in the initial activity setup – my balloon is re-used for all OverlayItems drawn on my map:

//Reference to our MapView 
MapView mapView = (MapView) activity.findViewById(R.id.mapview); 

//Get a LayoutInflater and load up the view we want to display. 
//The false in inflater.inflate prevents the bubble View being added to the MapView straight away 
LayoutInflater inflater = activity.getLayoutInflater(); 
LinearLayout bubble = (LinearLayout) inflater.inflate(R.layout.bubble, mapView, false); 

//Set up the bubble's close button 
ImageButton bubbleClose = (ImageButton) bubble.findViewById(R.id.bubbleclose);

bubbleClose.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        Animation fadeOut = AnimationUtils.loadAnimation(ResultsMapResultsDisplayer.this.activity, R.anim.fadeout);
        bubble.startAnimation(fadeOut);
        bubble.setVisibility(View.GONE);
    }
});

This next part is the important bit, and actually positions the bubble on the MapView using MapView.LayoutParams. It’s called by the onTap method of the ItemizedOverlay that contains my map markers:

private void displaySearchResultBubble(final SearchResult result) {

    map.removeView(bubble);
    bubble.setVisibility(View.GONE);

    TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
    venueName.setText(result.getName());

    TextView venueTime = (TextView) bubble.findViewById(R.id.venueopenfor);
    venueTime.setText("Open for " + result.getOpenFor() + "h");

    TextView venueFee = (TextView) bubble.findViewById(R.id.venuefee);
    venueFee.setText("Entry fee " + result.getPrice());

    MapView.LayoutParams params = new MapView.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
            result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);

    bubble.setLayoutParams(params);

    map.addView(bubble);        
    map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

    Runnable r = new Runnable() {
        public void run() {
            Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
            bubble.setVisibility(View.VISIBLE);
            bubble.startAnimation(fadeIn);
        }
    };

    Projection projection = map.getProjection();

    Point p = new Point();
    projection.toPixels(result.getPoint(), p);

    p.offset(0, -(bubble.getMeasuredHeight() / 2));
    GeoPoint target = projection.fromPixels(p.x, p.y);


    mapController.animateTo(target, r);

}

That’s it! It’s a fairly quick example but feel free to let me know in the comments if you want any more detail.


30 Responses to “Speech Bubble Popups containing a View for Android MapView”

  1. Thank you so much for this! I’ve gone through at least 5 methods this week to get this working, and yours is by far the easiest to understand.

  2. It would be nice to see full source code, thnx.

  3. Hey man, fantastic approach,

    Any chase of source code? Or a bit more information how you would do this with a custom overlayitems in the mapview?

  4. Hi could you please send me the source code.. i would really appreciate.

  5. HI, this is just the ticket, I seem to have hit all the things you have, and your research is sooo helpful, thank you.
    Please would you be kind enough to post the source/project?
    Thanks
    Wayne

  6. Hi all, I know there’ve been a few requests for source – I’ve been a bit busy recently and can’t put the source for the whole app I’m working on up. Will try and knock up a small example project showing this for you very soon though, sorry for the delay!

  7. Hi Dave,
    Thank you very much for this valuable post. I was searching here and there to find how to show a pop up window, but finally your valuable post guided me to successfully achieve the task. Thank you very much again.

  8. Hi could you please send me the source code.. i would really appreciate.

  9. Just perfect!!!

    I also had the reflexion steps you had and also conclued that this way was the best approach.

    I just was missing the animate map part.

    Thanks!!!!

  10. Hi Dave,

    working on an app, too. But I’M not quite familiar with the Layout-stuff yet. Would help, if you could show up a small working example :) Showing all the .xml-files would be great too. Thank you for this guide, so far.

  11. Hi, could you send to me full code… i’m new in android and need examples for training. my e-mail ov_sasha@mail.ru
    Thx

  12. Can you please provide your XML code for the R.layout.bubble?

  13. Thank you very much, it works perfectly! :-)

  14. Hallo Igor,

    look into the layout of mapviewballoons. you need a linearlayout with second linearlayout which contains e.g. textviews for your text and besides you need a imagebutton oder imageview for your close button. the background of your bubble you have to create.

  15. Michael,
    do you know if this only works with maps, or with any view/activity?

  16. Dave,
    Simply great…!!

  17. Please provide the source code..coz i m using mapactvity not by extending activity

  18. Thank you very nuch man been searching for this for a while now you have saved me :)

  19. Thank you for this example! I’ve been searching for a way to do this and nothing has been this clean and easy to understand. I knew it had to be related to adding the custom popup view to the MapView group.

  20. Hi Dave, can you please send me the source code of this, because I’m new to Android.. Thanx, BR

  21. please post the source code i require the actually customization of ballon and specially the way you over ride the piant method

  22. hi davee please mail me the source code i need it please…

  23. hi,
    thx for this sample
    please post the source code
    amine_was@hotmail.com

  24. Sorry for the delay on getting the source up everyone! I’ve added a link at the top of the post in case anyone is still interested.

  25. Hi Dave,
    Can you please help me to understand what is
    “ResultsMapResultsDisplayer”
    or “SearchResult” and where did you get these methods from?? (should it be recognized from somewhere???)

    Hope to hear from you!
    thanks,
    Ran

  26. Great tutorial, thanks for sharing!

  27. Hi Dave, thanks a lot for this enormous help. I would like to have the entire source code. However, the link at the top of the post does not contain it, it redirects to an empty page. Could you please upload it again or perhaps send it to my by email? estean.sm@hotmail.com

    Thank you very much and good job !!!

  28. Hi Esteban. The link seems to work ok here – it will redirect you to a specific java source file within the project on github. Can you browse other projects on github ok?

    The link to the whole project is here if that helps: https://github.com/actionshrimp/lastorders

  29. Dave,

    In line 74 of your XMLPRCSearcher.java file, XMLRPCClient client = new XMLRPCClient(“http://actionshrimp.com:7080″); — is triggering an error. Error Message (displaying in the dialog box when run in the emulator): “Unable to fetch results: org.apache.http.conn.HttpHostConnectException: Connection to http://actionshrimp.com:7080 refused…”

    I also attempted to access http://actionshrimp.com:7080 on my internet browser and page is unable to load. Can you clarify if the page is either down? Or point me to another alternative way to access the list? Thanks.

  30. Hi Kobe,

    I’m not running that service on actionshrimp.com anymore unfortunately. However, you can run it yourself if you have python installed, it’s here: https://github.com/actionshrimp/lastorders/tree/master/lastorders-server

    Unfortunately I couldn’t put the actual data I was using up alongside this source as it wasn’t mine to share, but if you put a few rows in a mysql table so that the queries in the python XMLRPC server code will work you should be able to call it ok.

Leave a Reply

Other posts:
« | »