Android菜單詳解——理解android中的Menu

來源:互聯網
上載者:User

標籤:

轉載)Android菜單詳解——理解android中的Menu  (2012-11-25 18:52:30) 轉載▼
標籤:  雜談 分類: android開發知識(轉載)

原文參考:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html

Android菜單詳解——理解android中的Menu前言

今天看了pro android 3中menu這一章,對Android的整個menu體系有了進一步的瞭解,故整理下筆記與大家分享。

PS:強烈推薦《Pro Android 3》,是我至今為止看到的最好的一本android書,中文版出到《精通Android 2》。

理解Android的菜單

菜單是許多應用程式不可或缺的一部分,Android中更是如此,所有搭載Android系統的手機甚至都要有一個"Menu"鍵,由此可見菜單在Android程式中的特殊性。Android SDK提供的菜單有如下幾種:

  1. 選項菜單:最常規的菜單,android中把它叫做option menu
  2. 子功能表:android中點擊子功能表將彈出懸浮視窗顯示子功能表項。子功能表不支援嵌套,即子功能表中不能再包括其他子功能表。
  3. 操作功能表:android中長按視圖控制項後出現的菜單,windows點擊右鍵彈出的菜單即操作功能表
  4. 表徵圖菜單:這個比較簡單,就是帶icon的功能表項目,需要注意的是子功能表項、操作功能表項目、擴充功能表項目均無法顯示表徵圖
  5. 選擇菜單(alternative menu):用的比較少,以後單獨介紹,本文先跳過(其實是我還沒弄明白啦o(≧v≦)o~~)
  6. 擴充菜單:選項菜單最多隻能顯示6個功能表項目,超過6個時,第6個功能表項目會被系統替換為一個叫“更多”的子功能表,原來顯示不下的功能表項目都作為“更多”菜單的子功能表項。如:

        

        第6個功能表項目自動變為“更多”              點擊“更多”顯示其他功能表項目

Android3.0又引入了一個叫action bar的東西,本文不做講解,大家自己google。

android.view.Menu介面代表一個菜單,android用它來管理各種功能表項目。注意我們一般不自己建立menu,因為每個Activity預設都內建了一個,我們要做的是為它加功能表項目和響應功能表項目的點擊事件。android.view.MenuItem代表每個功能表項目,android.view.SubMenu代表子功能表。其三者的關係可以用來表示

  

上面說過,每個activity包含一個菜單,一個菜單又能包含多個功能表項目和多個子功能表,子功能表其實也是菜單(因為它實現了Menu介面),因此子功能表也可以包含多個功能表項目。SubMenu繼承了Menu的addSubMenu()方法,但調用時會拋出執行階段錯誤。OnCreateOptionsMenu()和OnOptionsMenuSelected()是activity中提供了兩個回調方法,用於建立功能表項目和響應功能表項目的點擊。

建立options menu

之前提到,Android的activity已經為我們提前建立好了android.view.Menu對象,並提供了回調方法onCreateOptionsMenu(Menu menu)供我們初始化菜單的內容。該方法只會在選項菜單第一次顯示的時候被執行,如果你需要動態改變選項菜單的內容,請使用 onPrepareOptionsMenu(Menu)

 

@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// 調用父類方法來加入系統功能表
// 雖然目前android還沒有系統功能表,但是為了相容到以後的版本,最好加上
super.onCreateOptionsMenu(menu);

// 添加功能表項目(多種方式)
// 1.直接指定標題
menu.add("功能表項目1");
// 2.通過資源指定標題
menu.add(R.string.menuitem2);
// 3.顯示指定功能表項目的組號、ID、排序號、標題
menu.add(
1, //組號
Menu.FIRST, //唯一的ID號
Menu.FIRST, //排序號
"功能表項目3"); //標題

// 如果希望顯示菜單,請返回true
returntrue;
}


上面的代碼示範了添加功能表項目的3種方法,下面解釋下第三種方法
add(int groupId, int itemId, int order,CharSequence title)。其中,第一個參數是組號,android中你可以給菜單分組,以便快速地操作同一組的菜單。第二個參數指定每個功能表項目的唯一ID號,你可以自己指定,也可以讓系統來自動分配,在響應菜單時你需要通過ID號來判斷哪個菜單被點擊了。因此常規的做法是定義一些ID常量,但在android中有更好的方法,就是通過資源檔來引用,這個之後介紹。第三個參數代表功能表項目顯示順序的編號,編號小的顯示在前面。

給功能表項目分組
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// 添加4個功能表項目,分成2組
int group1 =1;
int gourp2 =2;
menu.add(group1, 1, 1, "item 1");
menu.add(group1, 2, 2, "item 2");
menu.add(gourp2, 3, 3, "item 3");
menu.add(gourp2, 4, 4, "item 4");
// 顯示菜單
returntrue;
}

 

你可以向上面這樣給功能表項目分組,分組之後就能使用menu中提供的方法對組進行操作了,如下:

 

menu.removeGroup(group1); //刪除一組菜單
menu.setGroupVisible(gourp2, visible); //設定一組菜單是否可見
menu.setGroupEnabled(gourp2, enabled); //設定一組菜單是否可點
menu.setGroupCheckable(gourp2, checkable, exclusive); //設定一組菜單的勾選情況

 

響應功能表項目

android提供了多種響應功能表項目的方式,下面一一介紹

1、通過onOptionsItemSelected方法

使用的最多方法是重寫activity類的 onOptionsItemSelected(MenuItem)回調方法,每當有功能表項目被點擊時,android就會調用該方法,並傳入被點擊功能表項目。

 

@Override
publicboolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
//響應每個功能表項目(通過功能表項目的ID)
case1:
// do something here
break;
case2:
// do something here
break;
case3:
// do something here
break;
case4:
// do something here
break;
default:
//對沒有處理的事件,交給父類來處理
returnsuper.onOptionsItemSelected(item);
}
//返回true表示處理完功能表項目的事件,不需要將該事件繼續傳播下去了
returntrue;
}

 

以上代碼可作為使用onOptionsItemSelected方法響應菜單的模板來使用,這裡為了方便起見將菜單ID寫入程式碼在程式裡,你可以使用常量或資源ID來使代碼更健壯。

2.使用監聽器

雖然第一種方法是推薦使用的方法,android還是提供了類似java swing的監聽器方式來響應菜單。使用監聽器的方式分為兩步:

 

//第一步:建立監聽器類
class MyMenuItemClickListener implements OnMenuItemClickListener {
@Override
publicboolean onMenuItemClick(MenuItem item) {
// do something here...
returntrue; //finish handling
}
}

//第二步:為功能表項目註冊監聽器
menuItem.setOnMenuItemClickListener(new MyMenuItemClickListener());

 

android文檔對onMenuItemClick(MenuItem item)回調方法的說明是"Called when a menu item has been invoked. This is the first code that is executed; if it returns true, no other callbacks will be executed." 可見該方法先於onOptionsItemSelected執行

3.使用Intent響應菜單

第3種方式是直接在MenuItem上調用setIntent(Intent intent)方法,這樣android會自動在該菜單被點擊時調用startActivity(Intent)。但是個人認為與其這樣還不如直接在onOptionsItemSelected的case裏手動調用startActivity(Intent)來的直觀。

Android菜單詳解(三)——SubMenu和IconMenu 

我們在上一篇介紹了如何在Android中建立和響應選項菜單,今天我們將探索子功能表和表徵圖菜單。

子功能表Sub Menu

 

子功能表提供了一種自然的組織功能表項目的方式,它被大量地運用在windows和其他OS的GUI設計中。Android同樣支援子功能表,你可以通過addSubMenu(int groupId, int itemId, int order, int titleRes)方法非常方便的建立和響應子功能表。

@Override 
publicboolean onCreateOptionsMenu(Menu menu) { 
int base = Menu.FIRST; 
// 一個menu可以包括多個子功能表 
SubMenu subMenu = menu.addSubMenu(base, base+1, Menu.NONE, "系統設定"); 
// 子功能表可以包括多個功能表項目 
MenuItem menuitem1 = subMenu.add(base, base+1, base+1, "顯示設定"); 
subMenu.add(base, base+2, base+2, "網路設定"); 
subMenu.add(base, base+3, base+3, "進階設定"); 
subMenu.add(base, base+4, base+4, "安全設定"); 

// 子功能表項不支援顯示表徵圖,這樣做是沒意義的,儘管不會報錯! 
menuitem1.setIcon(R.drawable.displaysettings); 

//但是子功能表本身是支援表徵圖的 
subMenu.setIcon(R.drawable.settings); 

// 顯示菜單請返回true 
returntrue; 
}

  

上面的代碼示範了如何建立子功能表,其功能表項目的響應其實就是普通功能表項目的響應,上一篇已經作了詳細介紹,這裡不再贅述。Android中可以為子功能表添加表徵圖,但是不會顯示其功能表項目的表徵圖,這一點需要留意。除了代碼中的setIcon(int iconRes)方法,還有一個setHeaderIcon(int iconRes)方法可以添加子功能表項欄目的標題表徵圖,效果如上面第三張圖。

最後需要強調的是,Menu可以包含多個SubMenu,SubMenu可以包含多個MenuItem(這三者之間的關係見Android菜單詳解(一)——理解Android中的Menu),但是SubMenu不能包含SubMenu,及子功能表不能嵌套!!!下面的代碼能通過編譯,但會在運行時出錯。

subMenu.addSubMenu("又一個子功能表");
表徵圖菜單Icon Menu

Android支援在菜單上顯示各種各樣的表徵圖,這一點我們在上面建立子功能表時已經用到了。表徵圖菜單嚴格上說並不算是一種菜單的新類型,它的使用也很簡單,之所以單獨設一節是為了說明使用Icon的一些限制。Android中並不是所謂的功能表項目都能加標,以下功能表項目都是不可以的(這並不意味著程式會報錯,而是運行時表徵圖得不到顯示):

  • 擴充的功能表項目。如果不理解什麼是擴充的菜單,可以參考Android菜單詳解(一)——理解Android中的Menu
  • 子功能表的功能表項目
  • 操作功能表的功能表項目

除此以外,帶Icon的功能表項目不能加上複選框(check mark)。總之,雖然精美的表徵圖能給我們的應用增色不少,但是濫用表徵圖也是會適得其反的,Android SDK給表徵圖菜單加的這些限制也算是有效防止我們濫用表徵圖了吧。

結語

本篇介紹了Android中的子功能表和給功能表項目加Icon時需要注意的幾點,下一篇《Android菜單詳解(四)——使用操作功能表ContextMenu》將介紹操作功能表Context Menu的使用。

之前在《Android菜單詳解(二)——建立並響應選項菜單》和《Android菜單詳解(三)——SubMenu和IconMenu》中詳細講解了選項菜單,子功能表和表徵圖菜單。今天接著細說另一種被廣泛使用的菜單——操作功能表Context Menu。

ContextMenu簡介

在Windows中,我們已經習慣了在檔案上單擊右鍵來執行“開啟”、“重名名”、“剪下”、“刪除”等操作,這個右鍵彈出的菜單就是操作功能表。你可能會笑道:“哈哈,你不會連快速鍵都不會用吧?”。咳咳,這個。。。舉個例子嘛。沒錯,windows中快速鍵能協助我們提高操作的效率,但是android中這招可不管用嘍,注意:android的操作功能表項目是不能用快速鍵的。因為手機的操作方式與使用滑鼠的PC操作方式不同,android是通過長按某個視圖元素來彈出操作功能表的(PS:現在大多數智能機是全觸屏的,沒有物理鍵盤,更沒有使用快速鍵的需要了,這項革新要歸功於喬布斯在07發布的革命手機iPhone,老喬退休了,向他致敬!)。除此之外,甚至連表徵圖和子功能表都無法用在Android的操作功能表項目中。那麼,Android的操作功能表到底如何使用?見

,操作功能表繼承了android.view.Menu,因此我們可以像操作Options Menu那樣給操作功能表增加功能表項目。操作功能表與Options Menu最大的不同在於,Options Menu的擁有者是Activity,而操作功能表的擁有者是Activity中的View。每個Activity有且只有一個Options Menu,它為整個Activity服務。而一個Activity往往有多個View,並不是每個View都有操作功能表,這就需要我們顯示地通過registerForContextMenu(View view)來指定

儘管操作功能表的擁有者是View,產生操作功能表卻是通過Activity中的onCreateContextMenu(ContextMenumenu, View v, ContextMenu.ContextMenuInfo menuInfo)方法,該方法很像產生Options Menu的onCreateOptionsMenu(Menu menu)方法。兩者的不同在於,onCreateOptionsMenu只在使用者第一次按“Menu”鍵時被調用,而onCreateContextMenu會在使用者每一次長按View時被調用,而且View必須已經註冊了操作功能表。

另一個值得注意的就是中的ContextMenuInfo,該類的對象被傳入onCreateContextMenu(ContextMenumenu, View v, ContextMenu.ContextMenuInfo menuInfo)方法,那麼它有什麼用呢?有時候,視圖元素需要向操作功能表傳遞一些資訊,比如該View對應DB記錄的ID等,這就要使用ContextMenuInfo。需要傳遞額外資訊的View需要重寫getContextMenuInfo()方法,返回一個帶有資料的ContextMenuInfo實作類別對象。

介紹了這麼多,下面給出一個demo示範如何建立和響應操作功能表:

1.在activity的onCreate(...)方法中為一個view註冊操作功能表

2.在onCreateContextMenuInfo(...)中產生操作功能表。

3.在onContextItemSelected(...)中響應操作功能表項目。

Demo:使用操作功能表

 

1)註冊操作功能表

publicclass SampleContextMenuActivity extends ListActivity { 
privatestaticfinal String TAG ="SampleContextMenuActivity"; 

@Override 
protectedvoid onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
// 顯示列表 
simpleShowList(); 
// 為所有清單項目註冊操作功能表 
this.registerForContextMenu(getListView()); 


privatevoid simpleShowList() { 
// list item 
String[] files =new String[] { 
"檔案1", 
"檔案2", 
"檔案3", 
"檔案4" 
}; 
// simple array adapter 
ArrayAdapter<</SPAN>String> adapter =new ArrayAdapter<</SPAN>String>( 
this, 
android.R.layout.simple_list_item_1, 
files); 
// set adapter 
this.setListAdapter(adapter); 
Log.v(TAG, "show simple list"); 

}

 

2)產生操作功能表

在activity中重寫方法。

@Override 
publicvoid onCreateContextMenu(ContextMenu menu, View v, 
ContextMenuInfo menuInfo) { 
Log.v(TAG, "populate context menu"); 
// set context menu title 
menu.setHeaderTitle("檔案操作"); 
// add context menu item 
menu.add(0, 1, Menu.NONE, "發送"); 
menu.add(0, 2, Menu.NONE, "標記為重要"); 
menu.add(0, 3, Menu.NONE, "重新命名"); 
menu.add(0, 4, Menu.NONE, "刪除"); 
}

 

3)響應操作功能表項目

與響應options menu類似,唯一的不同是可以通過menu info獲得額外的資訊。

@Override 
publicboolean onContextItemSelected(MenuItem item) { 
// 得到當前被選中的item資訊 
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); 
Log.v(TAG, "context item seleted ID="+ menuInfo.id); 

switch(item.getItemId()) { 
case1: 
// do something 
break; 
case2: 
// do something 
break; 
case3: 
// do something 
break; 
case4: 
// do something 
break; 
default: 
returnsuper.onContextItemSelected(item); 

returntrue; 
}

運行程式,多次喚出操作功能表,注意LogCat的輸出,onCreateContextMenu每一次都被調用了。

結語

至此,我們介紹完了android中的各種常用菜單,但是目前為止我們都是通過寫入程式碼來增加功能表項目的,android為此提供了一種更便利的方式,將在下一節“使用XML產生菜單”中介紹。

Android菜單詳解(五)——使用XML產生菜單 

回顧前面的幾篇,我們都是直接在代碼中添加功能表項目,給功能表項目分組等,這是比較傳統的做法,它存在著一些不足。比如說,為了響應每個功能表項目,我們需要用常量來儲存每個功能表項目的ID等。為此,Android提供了一種更好的方式,就是把menu也定義為應用程式的資源,通過android對資源的本地支援,使我們可以更方便地實現菜單的建立與響應。這一篇就介紹如何使用XML檔案來載入和響應菜單,我們需要做這幾步:

  1. 在/res目錄下建立menu檔案夾
  2. 在menu目錄下使用與menu相關的元素定義xml檔案,檔案名稱是隨意的,android會自動為其產生資源ID。例如:R.menu.mainmenu對應menu目錄的mainmenu.xml資源檔
  3. 使用xml檔案的資源ID,將xml檔案中定義的功能表項目添加到menu對象中
  4. 響應功能表項目時,使用每個功能表項目對應的資源ID

下面就使用xml的方式完成《Android菜單詳解(二)——建立並響應選項菜單》中的options menu。

定義菜單資源檔

在res目錄下建立menu檔案夾,在menu下建立一個xml資源檔,我這裡叫做mainmenu.xml

Android菜單詳解——理解android中的Menu

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.