actionshrimp.com

fun and geekery

12  05 2011

Speech Bubble Popups containing a View for Android MapView

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

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 discovered 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) {
	//Hide the bubble if it's already showing for another result
	map.removeView(bubble);
	bubble.setVisibility(View.GONE);

	//Set some view content
	TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
	venueName.setText(result.getName());

	//This is the important bit - set up a LayoutParams object for positioning of the bubble.
	//This will keep the bubble floating over the GeoPoint result.getPoint() as you move the MapView around,
	//but you can also keep the view in the same place on the map using a different LayoutParams constructor
	MapView.LayoutParams params = new MapView.LayoutParams(
		LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
 		result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);

	bubble.setLayoutParams(params);

	map.addView(bubble);
	//Measure the bubble so it can be placed on the map
	map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

	//Runnable to fade the bubble in when we've finished animatingTo our OverlayItem (below)
	Runnable r = new Runnable() {
		public void run() {
			Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
			bubble.setVisibility(View.VISIBLE);
			bubble.startAnimation(fadeIn);
		}
	};

	//This projection and offset finds us a new GeoPoint slightly below the actual OverlayItem,
	//which means the bubble will end up being centered nicely when we tap on an Item.
	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);

	//Move the MapView to our point, and then call the Runnable that fades in the bubble.
	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.


20 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

Leave a Reply

Other posts:
« |