Cyril Mottier

“It’s the little details that are vital. Little things make big things happen.” – John Wooden

Meet Polaris, a Map Library for Android

It’s been almost three years since Google last updated the Google Maps framework for Android. As you all know, this external library can be used to integrate map-related features into your applications. Unfortunately, in addition to getting old, this framework also suffers from a lot of limitations. I’ve recently spent a lot of time working on a map-based application of mine called AVélov and encountered a lot of issues while developing it. To make my life easier (as well as yours), I started creating a library with highly reusable components.

I am pleased to announce Polaris: a brand new map library that completely rethinks the way you use MapView in your application. Polaris' philosophy is based on 3 main rules:

  • Make the user’s life easier
  • Make the developer’s life easier
  • Make the resulting map look polished and natural

Prior to giving you some details about the library and what it can do, here are all of the resources you can use to download and test the library:

In practice, the Polaris library is an extension of the Google Maps External Library that fills some important gaps. For instance, it provides a lot of amazingly useful and powerful additions to the regular MapView. Here is a short (but still incomplete) list of some of the features supported by the Polaris library:

Gesture support

One of the major drawbacks of MapView is the lack of support for basic gestures such as the well-known double tap to zoom. Not providing developers with a gestures-enabled map reduces consistency among map-based application. Users usually expect all MapView to supply at least the exact same set of gestures regardless of the application being used. As a consequence, having MapViews not recognizing the gestures supported by the built-in Maps application can greatly frustrate users.

Polaris automatically handles essential gestures. The list below gives you an exhaustive catalogue of the available gestures as of version 1.0:

  • Single tap on map: opens, if necessary, the callout associated to the tapped marker
  • Double tap on map: zooms in focusing on the tapped location
  • Long press on map: does nothing by default. Clients may assign a OnMapViewLongClickListener to the PolarisMapView to be notified of long presses
  • Double tap on map callout: zooms in and pans to the maximum level of detail available

Effortless map annotating

PolarisMapView drastically simplifies addition of markers to a MapView by getting rid of the ItemizedOverlay (at least from a developer point of view) and introducing Annotations. Annotation is an extension of OverlayItem containing map-related information such as coordinates of a point, a title, a snippet and an optional marker Drawable. Annotating a PolarisMapView consists on building a list of Annotations and adding it to the map with the setAnnotations(List, int) or setAnnotations(List, Drawable) method. To sum up it only requires a few lines of code to annotate your map:

// Create a new list of Annotations
List<annotation> annotations = new ArrayList<annotation>();
annotations.add(new Annotation(new GeoPoint(), "Paris", "The city of love"));

// Set the Annotations to the PolarisMapView
mPolarisMapView.setAnnotations(annotations, R.drawable.default_marker);

One of the main advantage of using Annotations over OverlayItem is map callouts are automatically managed for you. Indeed, out of the box, the OverlayItem contains two Strings: a title and a snippet. Unfortunately, no matter how hard you search into the documentation, you will notice these Strings are never ever used! PolarisMapView automatically displays a map callout when the underlying annotation is tapped which makes map annotating insanely easy.

Map callout variable anchor positioning

Most (or should I say all) map-based applications uses 9-patches as map callout backgrounds. While 9-patches are great in most cases, they don’t allow variable stretching of the stretchable areas. As a consequence, it is not possible to make a map callout which positions an arrow depending on the position of the point of interest. Polaris includes a MapCalloutDrawable which allows variable positioning of the anchor.

This improvement is largely used by the Polaris library to get a more polished map. Indeed, while third-party applications usually center the map on the tapped OverlayItem, and the Maps app scrolls to make the callout entirely visible, PolarisMapView shows map callouts trying to reduce map scrolls as much as possible.

Built-in “user tracking” mode

In order to track the user location, The Google Maps external library provides a dedicated Overlay call MyLocationOverlay. This overlay displays a tiny blinking blue dot surrounding by a translucent blue disc describing the accuracy of the fix. Unfortunately, this Overlay is just an indication of the user location. There absolutely is no way to interact with it. PolarisMapView greatly enhances, while still simplifing, user tracking. With only one call to setUserTrackingEnabled(true), the Polaris library starts tracking the user location and displays a button similar to the one in the Maps application. When clicked this button centers the map on the user’s location.

Automatic built-in zoom controls

Android can run on a large diversity of devices. Nowadays, the vast majority of these devices support multi-touch gestures. However, there are still some others that don’t (especially lower-end devices). PolarisMapView seamlessly displays zoom controls only when required. It relieves the developer of the burden of checking the hardware capabilities of the device while maximizing the visible portion of the map on modern devices by hiding useless controls.

Natural map callouts transitions

PolarisMapView animates all transitions when showing and/or dismissing map callouts. Making a demonstration of the animation in a blog post is obviously not possible so I highly suggest to you to look at the PolarisSample app. Animated transitions results in a more natural and more polished map callout rendering.

Additional listeners

The default Google Maps External Library is cruelly lacking of listeners notifying the developer when the current state of the map has changed. For instance, there is no way to listen to changes on the visible region of the map (i.e. when the map has been zoomed and/or panned). Polaris includes additional listeners such as the OnRegionChangedListener. It can be particularly useful in order to lazy load annotations depending on the currently visible region.

As you can easily imagine, PolarisMapView relies on MapView while trying to be as transparent as possible. As a consequence, PolarisMapView offers the exact same features MapView offers and also suffers from some bugs related to the Google Maps external library. However there is a limitation when adding Overlays to the PolarisMapView. You must not use the getOverlays() method in MapView1 and use the addOverlay(Overlay), removeOverlay(Overlay) and similar methods instead. Moreover, you need to bind the onStart() and onStop() to your MapActivity equivalents. These methods are necessary to notify the PolarisMapView of the MapActivity lifecycle.

I really hope you will love the features and principles introduced in this first version of the Polaris library. Please keep in mind, you can obvisouly use it in your projects but you can also help the project submitting pull requests on GitHub. If you release an app that uses Polaris I would love to hear about it. Please contact me via Twitter, Google+, or email.

Thanks to @franklinharper for reading drafts of this and Marie Schweiz for designing the Polaris icon

  1. There is no way to by-pass this limitation due to the fact MapView makes the getOverlays() final.