在系統自動產生的 CalendarActivity.java 中,還有 onCreateOptionsMenu 和onOptionsItemSelected 尚未介紹,這兩個 Methods 是跟「選單 (Menu)」相關的 Methods,在 ActionBar 的右側有個由三個正方形垂直排列形成的圖示,點下後可開啟選單,如下圖所示:
今天我們會嘗試在這選單裡增加一些選項,首先先來看 19 ~ 23 行的 onCreateOptionsMenu,按照昨天所學的,我們嘗試去找出第 21 行 getMenuInflater 這個 Method 的意義,按照其程式寫法,我們去查詢 ActionBarActivity 的說明文件 [1],結果順利找到了:「Returns a MenuInflater with this context.」,然而讀者可能無法完全瞭解其說明,何謂 Context?何謂 MenuInflater?首先說明何謂 Context,從 ActionBarActivity 的繼承關係可發現,其繼承了 Activity,而 Activity 又繼承了 Context 這個抽象類別 [2] (關於 Context 抽象類別的說明,請讀者自行參閱參考文件 [2]),因此 “Returns a MenuInflater with this context.”,此處可以說就是回傳 ActionBarActivity 的 MenuInflater。
那麼 MenuInflater 又是什麼呢?從其類別說明文件 [3],可知「This class is used to instantiate menu XML files into Menu objects.」,簡單說就是把一個選單 XML 文件轉換成 Menu 物件,此外我們可以在 MenuInflater 的說明文件查詢到 inflate 的使用方法,inflate 的第一個參數是一個 XML 檔的資源 ID,從程式填入的參數 R.menu.calendar,我們不難想到 /res/menu 下會有一個 名為calendar.xml 的 XML 檔,其內容如下:
1 <menu xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:app="http://schemas.android.com/apk/res-auto"
3 xmlns:tools="http://schemas.android.com/tools"
4 tools:context=".CalendarActivity" >
5 <item android:id="@+id/action_settings"
6 android:title="@string/action_settings"
7 android:orderInCategory="100"
8 app:showAsAction="never" />
9 </menu>
從第 6 行的 android:title 屬性,我們不難發現它就是「設定」這個選項,因此代表我們可以透過修改這個 XML 檔案來新增選項。筆者將 /res/menu/calendar.xml 修改成如下所示:
1 <menu xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:app="http://schemas.android.com/apk/res-auto"
3 xmlns:tools="http://schemas.android.com/tools"
4 tools:context=".CalendarActivity" >
5 <item
6 android:id="@+id/action_addbaby"
7 android:icon="@drawable/add"
8 android:title="@string/addbaby"
9 app:showAsAction="always" />
10 <item
11 android:id="@+id/action_babylist"
12 android:title="@string/babylist"
13 app:showAsAction="never" />
14 <item
15 android:id="@+id/action_mailtodeveloper"
16 android:title="@string/mailtodeveloper"
17 app:showAsAction="never" />
18 </menu>
總共有 3 個選項:「新增寶寶」、「寶寶列表」和「寄信給開發者」,此處要提醒讀者的是,您必須在 strings.xml 新增必要的字串資源 (addbaby, babylist, mailtodeveloper)。首先來看 5 ~ 9 「新增寶寶」這個選項,第 6 行我們給這個選項一個 id,這個 id 會在等會要說明的 onOptionsItemSelected 中用到,第 9 行我們設定這個選項會永遠出現在 Action Bar,為什麼筆者會希望它永遠出現在 Action Bar 呢?因為使用這個 App 的第一個動作就是新增一個寶寶,因此放在明顯的地方才不會讓使用者不知道怎麼開始使用這個 App,因為這個選項會出現在 Action Bar,因此第 7 行我們也給這個選項一個圖示(後面讀者會看到,這個圖示只是一個單純的「+」符號),至於「寶寶列表」和「寄信給開發者」這兩個選項就較為單純,給它們 id、設定顯示字串、設定不顯示於 Action Bar,執行結果如下圖所示:
現在我們已經幫我們 App 的選單新增了幾個選項,然而讀者不難發現,選項點選下去都沒有作用,為了讓選項發揮作用,我們必須修改 onOptionsItemSelected 裡的內容,自動產生的 CalendarActivity.java,其原本 onOptionsItemSelected 的內容如下所示:
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
從程式碼我們不難看出,if (id == R.id.action_settings) 那個 if 區塊是處理原本「設定」選項要做的事情,然而我們已經刪除了「設定」選項,另外新增了「新增寶寶」、「寶寶列表」和「寄信給開發者」三個選項,因此可先把 onOptionsItemSelected 修改成如下所示,至此,讀者也應該能瞭解為什麼我們要在 /res/memu/calendar.xml 給每個選項一個專屬的 id:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_addbaby:
return true;
case R.id.action_babylist:
return true;
case R.id.action_mailtodeveloper:
return true;
}
return super.onOptionsItemSelected(item);
}
至於這三個選項的實作細節,會留到明天再討論,筆者會介紹一個重要的類別:Intent。
參考資料:
[1] ActionBarActivity | Android Developers, https://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html
[2] Context | Android Developers, http://developer.android.com/reference/android/content/Context.html
[3] MenuInflater | Android Developers, https://developer.android.com/reference/android/view/MenuInflater.html