Saturday, May 14, 2011

[Android]Android MapView與Overlay實作演練

Android程式能夠很方便的跟google API做結合,而在手機建立MapView之前,必須先跟google申請google Map API Key。Key又分為兩種,一種是在開發測試時使用的debug key,另一個為軟體正式上架使用的key,兩者是不能互換使用的。也就是說,在開發時使用的Google Map API Key與正式上架的API Key是不一樣的。

Google MAP API裡面寫的很清楚,在此不做贅述。


申請完API Key之後,首先先建立包含mapView的Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
    <com.google.android.maps.MapView android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="Your Maps API Key goes here"
android:clickable="true"/>
</LinearLayout>

建立完之後main.xml之後,開始建立以下程式:

//import程式碼省略
public class MyMapView extends MapActivity{
private MapView mapView;
private MapController mapController;
private GeoPoint geoPoint;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.boarding_place);
        mapView = (MapView) findViewById(R.id.map);
        mapController = mapView.getController();
//設定衛星圖
        mapView.setSatellite(false);
//設定街道圖,此方法for2.2版本,若為2.3.3以上版本需改為mapView.setTraffic(true)
        mapView.setStreetView(true);
//設定地圖級距
        mapController.setZoom(18);
//設定世貿一館的座標
   geoPoint = new GeoPoint((int)(25.033489 * 1E6), (int)(121.561486 * 1E6));
   mapView.displayZoomControls(true);
   /* 將Map的中點移至GeoPoint */
   mapController.animateTo(geoPoint);
    }
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}

建立完程式之後,別忘了在設定檔中加入權限:

    <application .........>
        <activity........>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
<uses-library android:name="com.google.android.maps"/>
    </application>
    <uses-permission android:name="android.permission.INTERNET" />

此時開啟模擬器,已可以看到地圖了。

mapView

如果想要在地圖上加上需要的標籤跟文字該如何做呢?請改寫以下程式:

public class MyMapView extends MapActivity{
private MapView mapView;
private MapController mapController;
private GeoPoint geoPoint;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.boarding_place);
        mapView = (MapView) findViewById(R.id.map);
        mapController = mapView.getController();
//設定衛星圖
        mapView.setSatellite(false);
//設定街道圖
        mapView.setStreetView(true);
//設定地圖級距
        mapController.setZoom(18);
//設定座標
   geoPoint = new GeoPoint((int)(25.033489 * 1E6), (int)(121.561486 * 1E6));
   mapView.displayZoomControls(true);
   /* 將Map的中點移至GeoPoint */
   mapController.animateTo(geoPoint);
   //加入地圖標籤
        MapOverlay mapOverlay = new MapOverlay();
        List<Overlay> listOfOverlays = mapView.getOverlays();
        listOfOverlays.clear();
        listOfOverlays.add(mapOverlay);
    }

@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}

public class MapOverlay extends com.google.android.maps.Overlay {
@Override
        public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
            super.draw(canvas, mapView, shadow);
            Projection projection = mapView.getProjection();
            //—translate the GeoPoint to screen pixels—
            Point screenPts = new Point();
            projection.toPixels(geoPoint, screenPts);
            //—add paint—
            Paint paint = new Paint();
            paint.setColor(R.color.BLACK);
//設定文字大小
            paint.setTextSize(20);
            paint.setAntiAlias(true);
            paint.setFakeBoldText(true);
            //—add the first marker—
            Bitmap bmp = BitmapFactory.decodeResource( getResources(), R.drawable.pin);          
            canvas.drawBitmap(bmp, screenPts.x, screenPts.y, null);
            canvas.drawText("TWTC Exhibition Hall 1", screenPts.x - 50, screenPts.y, paint);
            //—add the second marker—
            Point screenPts2 = new Point();
        GeoPoint geoPoint2 = new GeoPoint((int)(25.035340* 1E6), (int)(121.563847* 1E6));
            projection.toPixels(geoPoint2, screenPts2);
            //Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint, transformed by the current matrix.
            canvas.drawBitmap(bmp,screenPts2.x ,screenPts2.y , null);
            //Draw the text, with origin at (x,y), using the specified paint.
            canvas.drawText("TWTC Exhibition Hall 3", screenPts2.x - 50, screenPts2.y, paint);
            return true;
        }
}
}

重新載入模擬器,便可以看到剛才加入的兩個標籤與文字。

mapView

Android官網上的MapView tutorial雖然是英文的,但是其實介紹的相當清楚,大家也可以自行參考Android Dev Guide

8 comments:

  1. 你好!!

    想請問一下
    你的針的圖檔
    是已經放在drawable的資料夾下了嗎?

    謝謝

    ReplyDelete
  2. 你好,我使用上述原始碼,但Map會出現正方形空白(空白中有X),請問是什麼問題呢?謝謝

    ReplyDelete
  3. 我應該附上個圖的,這樣說的確很難理解。後來問題點有找到,是mapView.setStreetView(true);這行,我改為mapView.setTraffic(true);地圖就能正常顯示了

    ReplyDelete
    Replies
    1. 您好,謝謝您的回應,不知道您的Android是包哪一個版本的?從您的留言上看來,google map API似乎有修改過方法,因為我在2.2中使用此方法是沒有問題的。在此再度謝謝您的回應,我會修改文章。

      Delete
  4. 您好,想請問如果想做一個按鈕可以切換顯示(讓他能隱藏/顯示)地圖上的標記點(圖釘)該怎麼做呢?
    有去爬過一些文章,都是只講到設定上去而已
    想請問版主大大會的話能否教學一下
    感恩~

    ReplyDelete
  5. 地圖上的標籤是透過以下程式加入:
    MapOverlay mapOverlay = new MapOverlay();
    List listOfOverlays = mapView.getOverlays();
    listOfOverlays.clear();//清除地圖標籤
    listOfOverlays.add(mapOverlay);//加入地圖標籤

    所以你可以放一個button,並設定onClickListener,在onClickLister中加入flag,利用flag=true或false去隱藏或顯示地圖標籤。

    good luck!

    ReplyDelete