ScalaMap is a wrapper of Android Google Maps API for Scala.
Sorry for my poor English, but I think this may be useful if you wnat develop Android w/ Google Maps API application using Scala.
Overview
Currently, it's not easy to use Android's Google Maps API for two reasons.
-
There is a bug in Scala compiler. If a Java library reference to a static inner class in another Java library, the compiler will complain that "classfile is broken" (Scala 2.7.7) or "Missing dependency" (Scala 2.8).
- Unfortunately, it is what happened in MapView, it return ViewGroup.LayoutParams in several public methods.
-
Scala cannot access Java protected static classes / fields / methods.
- That is what happened in ItemizedOverlay, where you should call protected static method boundCenter(Drawable drawable) or boundCenterBottom (Drawable drawable) in subclass's constructor.
To overcome this problem, I've created a simple wrapper library located at this GitHub repository. It's not prefect and has a lot limitations , but I think it should work.
License
This library is release under GNU Lesser General Public License. See COPYING AND COPYING.LESSER for details.
Install
This wrapper library use SBT (Simple Build Tool) as build system, it is not required, but will make things easier. You should install it.
- Download and install SBT following this instruction, it should be easy.
- Download the source code of ScalaMap.
- Unzip it to a directory called scalamap/
- Copy your android.jar and maps.jar library files to scalamap/lib/
- $ cd scalamap/
- $ sbt package
- After step 7, you should get a JAR file called scalamap-0.0.1.jar under target/ directory.
USAGE
-
Remember adding scalamap-0.0.1.tar.gz to your classpath when you compile your project.
-
Take a look at the example code below and project under demo/ directory.
-
Import
org.maidroid.scalamap._
-
Basically, you could use the following code to create a SMapView object, where R.id.mapview is pointed to a MapView object in layout file.
-
val sMapView = new SMapView (findViewById (R.id.mapview))
-
You should be able to use a SMapView object just like an ordinary MapView, but remember, it is a wrapper using composition instead of inheritance, so there are some methods is not implemented in this wrapper.
NOTE
-
If you need MapController, use sMapView.getSMapController() to get a SMapController wrapper object.
-
If you need hook listener to a MapView, use sMapView.getViewGroup() to get the MapView object as instance of ViewGroup.
-
DO NOT USE sMapView.getMapView() / s or you will get a compiler error message like "class is borken", YOU'VE BEEN WARNED.
-
There are two minor API difference:
- The constructor of SItemizedOverlay is (Drawable drawalbe, int mode), where mode is one of
BOUND_CENTER
,BOUND_CENTER_BOOTOM
, andNO_BOUND
in SItemizedOverlay. - SMapView.setReticleDrawMode takes an arguement of type Int, which is one of the following three value:
SMapView.DRAW_RETICLE_NEVER
,SMapView.DRAW_RETICLE_OVER
, andSMapView.DRAW_RETICLE_UNDER
.
CODE EXAMPLE
This is the code example corresponding to the tutorial Hellp, MapView on Android Developer site.
package org.bone; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.View; import android.widget.ZoomControls; import android.widget.LinearLayout; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.GeoPoint; import com.google.android.maps.OverlayItem; import com.google.android.maps.Overlay; import org.maidroid.scalamap.SMapView class HelloMap extends MapActivity { private lazy val layout = findViewById (R.id.zoomview). asInstanceOf[LinearLayout] private lazy val mapView = new SMapView (findViewById(R.id.mapview)) private lazy val mapOverlays = mapView.getOverlays private lazy val drawable = getResources. getDrawable (R.drawable.androidmarker) private lazy val itemizedoverlay = new HelloItemizedOverlay (drawable) override def isRouteDisplayed = false override def onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main) mapView.setBuiltInZoomControls (true) val point1 = new GeoPoint (19240000, -99120000) val point2 = new GeoPoint(35410000, 139460000) val overlayitem1 = new OverlayItem (point1, "", "") val overlayitem2 = new OverlayItem (point2, "", "") itemizedoverlay.addOverlay (overlayitem1) itemizedoverlay.addOverlay (overlayitem2) mapOverlays.add (itemizedoverlay) } }
package org.bone import android.graphics.drawable.Drawable import com.google.android.maps.OverlayItem import java.util.ArrayList import org.maidroid.scalamap.SItemizedOverlay import SItemizedOverlay.BOUND_CENTER_BOTTOM class HelloItemizedOverlay (drawable: Drawable) extends SItemizedOverlay[OverlayItem] (drawable, BOUND_CENTER_BOTTOM) { private lazy val mOverlays = new ArrayList[OverlayItem] override def createItem (i: Int) = mOverlays.get(i) override def size () = mOverlays.size() def addOverlay (overlay: OverlayItem) { mOverlays.add (overlay); populate (); } }
回響