2012年8月28日 星期二

第一支 Android App 上架,從無到有的全記錄 (4)

一個跟地圖有關的 App, 沒有地圖上的標記也是很奇怪的。所以,接下來我們要在地圖上加兩種標記。

首先我們要加上 Google Map API 提供的 MyLocationOverlay。

在 Main Activity 中宣告一個變數

private MyLocationOverlay m_MyLocationOverlay;

在 onCreate 函式裡,產生這個 Overlay,並且加入到 Map View 中。

m_MyLocationOverlay = new MyLocationOverlay(this, m_MapView);
m_MapView.getOverlays().add(m_MyLocationOverlay);

/*m_MyLocationOverlay.runOnFirstFix(new Runnable() {
    public void run() {
        m_MapView.getController().animateTo(m_MyLocationOverlay.getMyLocation());
    }
});*/

有一段程式碼註解起來了,這段程式碼的用意在,當我們取得 Location 後,把 Map View 上的地圖,搬移到我們所在的位置上。但是因為我們在 GeoUpdateListener 中也有相同的功能,所以,這段程式碼其實可有可無。

接著,在 Main Activity 上,我們覆寫兩個函式。

@Override
protected void onResume() {
    super.onResume();
    m_MyLocationOverlay.enableMyLocation();
    m_MyLocationOverlay.enableCompass();
}

@Override
protected void onPause() {
    super.onPause();
    m_MyLocationOverlay.disableMyLocation();
    m_MyLocationOverlay.disableCompass();
}

現在可以 Build 來測試看看。

device-2012-08-28-112023

如果用模擬器來跑的話,記得從模擬器上送出位置。

接下來,我們要來加上我們自己的標記。

首先,我抓了一個免費的藍色圖釘圖示。pin_blue加到 Android 專案的 resource 裡,名稱叫做 pin_blue。

然後,我們從 Map API 中的 ItemizedOverlay 抽象介面,實做一個叫做 PriLocOverlays 的類別。

public class PriLocOverlays extends ItemizedOverlay<OverlayItem>
{
    private static int MAXNUM = 50;
    private OverlayItem m_Overlays[] = new OverlayItem[MAXNUM];
    private int m_nCount = 0;

    public PriLocOverlays(Drawable defaultMarker) {
        super(boundCenterBottom(defaultMarker));
        // TODO Auto-generated constructor stub
    }

    @Override
    protected OverlayItem createItem(int i) {
        // TODO Auto-generated method stub
        return m_Overlays[i];
    }

    @Override
    public int size() {
        // TODO Auto-generated method stub
        return m_nCount;
    }

    public void addOverlay(OverlayItem overlay)
    {
        if (m_nCount < MAXNUM)
        {
            m_Overlays[m_nCount] = overlay;
            m_nCount++;
            setLastFocusedIndex(-1);
            populate();
        }
    }

}

OverlayItem 的陣列,我們必須要自己管理。我很簡單的只是用個固定陣列來放。然後再加個記數的變數。

createItem 以及 size 兩個函式是我們要實做的,就簡單的傳回陣列裡的物件跟數量就好了。要注意的是,這個 createItem 函式,並不真的需要去產生一個 Item,每次 Map View 需要更新 Overlay 時,都會呼叫這個函式。

在我們自己的 addOverlayItem 內,我們需要呼叫 populate 函式,通知 Map View 來更新這個 Overlay。並且,最好是在呼叫 populate 之前,呼叫 setLastFocusedIndex(-1),清掉之前的 Focus Item,否則咧,會因為找不到之前的 Focus Item 而讓 App Crash 的。( 我實際接到過這個問題的 Bug 回報,還好已經有神人找到問題解答了... )

接著,改 Main Activity,加入 PriLocOverlays 的變數,並且在 onCreate 中建立它。

Drawable drawable = this.getResources().getDrawable(R.drawable.pin_blue);
m_PrivateLocOverlay = new PriLocOverlays(drawable);
m_MapView.getOverlays().add(m_PrivateLocOverlay);

我們還需要有一個把目前位置建立成 OverlayItem 加入到 PrivateLocOverlay 裡的功能。就做在 Option Menu 裡吧...

在 Main Activity 加入函式。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.menu_settings)
    {
        OverlayItem overlay = new OverlayItem(m_MyLocationOverlay.getMyLocation(), "Test Loc", "");
        m_PrivateLocOverlay.addOverlay(overlay);
        //requestAddCurrentLocation();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

於是乎,程式跑起來就像這樣。

device-2012-08-28-131318

 

呃...

本來想,就先寫到這樣吧,後來又覺得該寫下這個...

我們在 PriLocOverlays 類別裡,可以覆寫 onTap ( int index ) 這個函式。

當地圖上的標記被點選到的時候,onTap 函式會被呼叫。這時候,我們可以用 index 取出 OverlayItem,進行處理。

@Override
protected boolean onTap(int index)
{
    OverlayItem overlayItem = m_Overlays[index];
    Toast.makeText(m_Activity, overlayItem.getTitle(), Toast.LENGTH_LONG).show();
    // TODO Auto-generated method stub
    return super.onTap(index);
}

我沒多做什麼,就是用 Toast 顯示了一下。

結果就類似這樣。

image

5 則留言:

黃小龍 提到...

我想問一下有辦法直接Override
MyLocationOverlay的Draw來改變圖示嗎?
我現在是用Overlay改變圖示來畫出
但似乎因為每次都要讀取畫面位置
導致有時候畫的時候就會產生超時
不知道有沒有什麼好的解決辦法?
謝謝

藍斯洛 提到...

我沒有試過,不過應該是可以 Override的

jack 提到...

你好,
跟著文章做,可以編譯正常執行,
但地圖是顯示空白方格,專案是google api,
有下載您google play的app,能正常顯示.
所以我想是不是google更新了API的使用?
因為我在模擬器及實機都不能正常顯示地圖,也在官方看到文章:
https://developers.google.com/maps/documentation/android/?hl=zh-TW
請問是這個原因造成的?感謝您.

小豬頭 提到...

你好,可否跟你請教一些有關於用Unity做Android的問題??如果可以的話,麻煩你寄個信或者留個email給我
這是我的信箱lovecoldcool@gmail.com
感謝你

hero 提到...

有上 google 申請金鑰嗎?
沒有金鑰畫面會變成空白喔