12
05
2011
Posted by Dave | Tags:
android,
balloon,
bubble,
Dialog,
LayoutParams,
MapView,
Overlay
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.
3
04
2011
Posted by Dave | Tags:
plugin,
vim,
xml,
xpath I’ve built a plugin that adds XPath search functionality to Vim. Check out the demo video below.
Features:
- Quick XPath search input with smart, context-sensitive tab completion
- Results shown in a pop-up results window. Jump to the line of a matching result easily.
- Debug invalid XML – jump to the the line number of an XML error from the results window
Requirements:
- Python support enabled in Vim
- lxml library installed for Python (ideally 2.7 or higher).
For more info, and to grab the plugin by downloading the vimball, visit my github:
https://github.com/actionshrimp/vim-xpath
Let me know what you think / any improvement suggestions in the comments below.
15
08
2010
Posted by Dave | Tags:
icecast,
ps3mediaserver,
radio,
spotify,
stream,
tutorial,
ubuntu
A post came up a couple of days ago on the Spotify “What’s new” feed: how to stream spotify wirelessly to your stereo, which got me thinking about something I’ve been after for a while – the ability to stream spotify audio to PS3. This is mentioned in the link, but the main method they talk about is for Windows, and a solution for mac is touched upon. I figured I’d have a go at doing this on Ubuntu.
Before you have a go at this, I should mention a slight drawback – there’s a fair delay on the audio steam that reaches the PS3, around 20 or 30 seconds. This makes it good for playing a playlist as background music, but if you’re wanting to be able to flick around loads of different songs then you might get a bit frustrated. Read on if you’re still keen…
Read more…
7
04
2009
Posted by Dave | Tags:
admin,
cake,
CakePHP,
pagescontroller,
routing,
tutorial For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass:
function beforeFilter(){
$admin = Configure::read('Routing.admin');
if (isset($this->params[$admin]) and $this->params[$admin]){
$this->layout = 'admin';
}
else {
$this->Auth->allow();
}
}
The problem with this however is static pages handled by the pages controller cannot be password protected. To resolve this problem, I had to overload the PagesController class that Cake comes with, and add in the required functionality. Part of the reason for doing this for me was to allow a setup where there was a password protected admin welcome page or control panel located at my_app_URL/admin, so I’ll show you the necessary routing to achieve that too.
Read more…
31
03
2009
Posted by Dave | Tags:
cake,
CakePHP,
tutorial,
Web,
website
In the first part of my CakePHP tutorial, I showed you how to use Cake’s Bake utility to set up the basic back end of an online illustration portfolio. In this part, I’ll tweak the automatically generated code into useable website and admin section and show you how to use some of Cake’s features along the way, including the Authentication component.
Read more…
28
03
2009
Posted by Dave | Tags:
bake,
cake,
CakePHP,
framework,
tutorial,
Web,
website
A friend of mine recently asked me to help him build an online portfolio for his illustration pieces, and I decided to use CakePHP 1.2 to get the back end up and running quickly. I thought someone might find a tutorial taking a simple website through from start to finish useful, so this tutorial series will do just that. This part of the series takes you through the first few steps I took to get the basic code together. You’ll need a web server and database server such as MySQL, and some basic PHP and webserver management knowledge. We’ll be using Cake’s “bake” utility to create the basic code as well, so you’ll need console access to your webserver, and PHP’s command line utility (in Ubuntu/PHP5 you can just install the package php5-cli).
Read more…
1
03
2009
Posted by Matt | Tags:
apache,
directory,
gallery,
lightbox,
tutorial
As you may know, if it can’t find an index.html the apache web server will show a list of files in the current directory. I was browsing through lists of images on my file server the other day and I thought, wouldn’t it be nice to have a next button? So I started digging around.
In the end I used a wonderful little script called Lightbox 2 and a bit of JavaScript Prototype magic to produce this (try clicking on the image files).
The directory listings are provided by an apache module going by the name of mod_autoindex. This module allows you to insert a custom header and footer through the directives HeaderName and ReadmeName. The plan is to insert some HTML that includes the Lightbox code and tags all the links to images with the rel=lightbox attribute that Lightbox uses to function.
Read more…
2
02
2009
Posted by Dave | Tags:
awesome,
awm,
tutorial,
ubuntu,
window Quick Note: This post was originally published on 02/02/2009, so is probably a bit outdated now.
Today I had a go at installing awesome window manager. awesome is a great tiling window manager, useful if you have a large monitor and are fed up with having one window taking up all the space when it doesn’t really need it all. For example, having firefox maximised on a 1920×1200 resolution monitor can mean you end up with very large sentences that spread across the screen, decreasing readability. Unfortunately the version of awesome in the Interpid repos is 2.3.2-1, which is now deprecated, and the current stable release is version 3.1-1.

The website suggests building from source – I attempted this but there are currently a couple of issues with compilation mentioned in the wiki, and even with the fix suggested I couldn’t quite get it to work – although I didn’t try too hard it must be said; instead I found another method which I will walk you through now.
Read more…
13
08
2008
Posted by Dave | Tags:
e2500,
quickcam,
skype,
tutorial,
ubuntu
I recently discovered the wonders of skype, and tried to get my new webcam working with it under linux, and of course this proved to be quite tricky. After much fiddling I eventually got it to work, hopefully these steps will work for you too.
Read more…
13
05
2008
Posted by Dave | Tags:
integration,
jsvi,
TiddlyWiki,
tutorial Note: This is a bit out of date now, but Chris Peplin has built a proper plugin for tiddlywiki which does this for the latest versions of everything. So check it out! If you’re still interested in the old way then read on…
When adding posts to my TiddlyWiki, I oft found myself craving vi, rather than a simple textarea. There were a few options that involved using a plugin for Firefox such as mozEx, and using an external program to edit textareas. However, I found a nice ‘integrated’ option instead.
Read more…