建立操作功能表
操作功能表提供了影響指定項目或UI中內容結構的動作。你能夠給任何View對象提供一個內容菜單,但是它們最常用於ListView、GridView或集合類型的View對象的項目中,使用者能夠執行每個項目上的動作。
有兩個方法來提供上下文動作:
1. 在一個浮動的內容菜單中提供上下文動作。當使用者在一個聲明支援操作功能表的View對象上長按(long-click)時,會顯示一個浮動的功能表項目列表(類似一個對話方塊)。每次使用者能夠在一個項目上執行的上下文動作。
2. 在上下文動作模式中提供上下文操作。這種模式是ActionMode類的一個系統實現,它在螢幕的頂部顯示一個帶有操作項目的上下文操作欄,這些操作能夠影響被選擇的項目。當這種模式被啟用,每次用於能夠在多重專案上執行一個操作(如果你的應用程式允許)。
注意:上下文操作模式在Android3.0(API 層級 11)和以上版本中才是有效,並且是顯示上下文操作的首選技術。如果你的應用程式支援的平台版本比3.0低,那麼就要在這些裝置上使用浮動菜單。
浮動操作功能表(左)和上下文操作欄(右)的
建立浮動的操作功能表
以下是建立浮動的操作功能表的步驟:
1. 通過調用registerForContextMenu()方法把View對象註冊給被關聯的內容菜單,這個方法接受View對象參數。如果你的Activity使用一個ListView或GridView對象,並你想給對象中的每個項目都提供相同的內容菜單,可以通過把ListView或GridView對象傳遞給registerForContextMenu()方法來註冊一個內容菜單的所有功能表項目。
2. 實現Activity或Fragment中的onCreateContextMenu()方法。
當被註冊的View對象接受到一個長按(long-click)事件時,系統會調用你的onCreateContextMenu()方法。這是你定義功能表項目的地方,通常通過裝載一個菜單資源的方法來完成,例如:
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
MenuInflater對象允許你從一個菜單資源中載入內容菜單。回調方法中參數包含了使用者選擇的那個View對象和一個ContextMenu.ContextMenuInfo對象,這個對象提供有關選擇項目的額外資訊。如果你的Activity有幾個View對象,並且每個View都提供了一個不同的內容菜單,你可以使用這些參數來判斷哪個內容菜單被裝載了。
3. 實現onContextItemSelected()回調方法。
當使用者選擇一個功能表項目時,系統會調用這個方法,因此你能在此執行相關的操作。如:
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
getItemId()方法查詢被選擇的功能表項目的ID,你應該使用android:id屬性給XML檔案中的每個功能表項目分配一個ID值。
當你成功的處理一個功能表項目時,會返回true。如果你沒有處理這個功能表項目,你應該把這個功能表項目傳遞給父類的實現。如果你的Activity包含了Fragment對象,Activity會首先接受這個回調。當未處理時,通過調用父類的回調方法,系統會把這個事件傳遞每個Fragment對象中的回調方法。一次一個(按照每個Fragment對象被添加的順序),直到返回true或false。(Activity和android.app.Fragment的預設實現都返回false,因此當未處理時,你應該始終調用父類的實現。)
使用上下文操作模式
上下文操作模式是ActionMode類的一個系統實現,它關注使用者跟執行內容操作的互動。當使用者通過選擇一個項目使這種模式成為可能的時候,一個上下文操作欄就會顯示在螢幕的頂部,並展現出使用者在當前被選擇的項目上能夠執行的操作。當這種模式成為可能時,使用者能夠選擇多重專案(如果應用程式允許),或取消選擇項目,並且可繼續在Activity內瀏覽。當使用者取消了所有選擇的項目、按下BACK按鈕、或選擇操作欄左邊的“執行”操作時,這種操作模式就會被禁止,並且上下文操作欄也會被隱藏。
注意:上下文操作欄不必跟操作欄關聯。它們獨立的操作,上下文操作欄甚至可以顯示在操作欄位置之上。
如果你依賴Android3.0(API層級 11)或更高的版本,你通常應該使用上下文操作模式來表現上下文操作,而不是浮動內容菜單。
對於那些提供上下文操作的View對象,你通常應該在以下兩種事件之上調用上下文操作模式:
1. 使用者在View對象上執行一個長按(long-click)操作。
2. 使用者選擇了一個複選框或View對象中類似複選框的UI組件。
你的應用程式如何調用上下文操作模式,並給每個操作定義行為,依賴於你的設計。有以下兩種基本的設計:
1. 針對個別的、任意的View對象的上下文操作。
2. 針對ListView或GridView對象中項目組的批處理上下文操作(允許使用者選擇多重專案,並這些選擇的項目上執行一個操作)。
針對個別View對象的上下文操作模式
如果你只想在使用者選擇特定的View對象時,調用上下文操作模式,應該按以下方法來做:
1. 實現ActionMode.Callback介面。在它的回調方法中,你能夠針對上下文操作欄指定動作,在操作項目上響應點擊事件和處理針對這個操作模式的其他生命週期事件。
2. 在顯示這個操作欄時,調用startActionMode()方法(如使用者長按(long-click)對應的view對象時)。
如:
1. 實現ActionMode.Callback介面:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
我們注意到,這些回調方法處理把ActionMode對象傳遞給關聯的事件之外,幾乎完全跟選項菜單的回調方法相同。你能夠使用ActionMode的API對CAB(Context Action Bar)進行各種改變,如用setTitle()和setSubtitle()方法修改標題和子標題(有益於指示有多少項目被選擇了)。
我還看到,上例中,當操作模式被銷毀時,把mActionMode變數設定為null,接下來,你能看到它是如何被初始化的,以及如何把成員變數儲存在你的Activity或Fragment中。
2. 在適當的時機調用startActionMode()方法啟用上下文操作模式,如在響應一個View對象的長按事件時:
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
當你調用startActionMode()方法時,系統返回被建立的ActionMode對象。通過把這個對象儲存在一個成員變數中,你能夠在對其他事件的響應中對操作功能表進行改變。在上例中,在啟動這種操作模式之前,通過檢查ActionMode對象的執行個體是否為null,來確保這個對象執行個體不被重複建立。
在ListView或GridView對象中的批處理上下文操作
如果在ListView或GridView對象(或是另外的AbsListView類的擴充)中有一個項目的集合,並且你想要允許使用者對其執行批處理操作,那麼你應該按如下的方法做:
1. 實現AbsListView.MultiChoiceModeListener介面,並且要用setMultiChoiceModeListener()方法把它設定給ViewGroup對象。在這個監聽器的回調方法中,你能夠給這個上下文操作欄指定動作,響應在操作項目上的點擊事件,並且處理從ActionMode.Callback介面中繼承來的其他回調方法。
2. 調用帶有CHOICE_MODE_MULTIPLE_MODAL參數的setChoiceMode()方法。
例如:
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an
invalidate() request
return false;
}
});
現在,當使用者用長按事件選擇一個項目時,系統會調用onCreateActionMode()方法,並顯示帶有特定操作的上下文操作欄。同時在上下文操作欄顯示時,使用者還能繼續選擇其他的項目。
在某些情境中,上下文操作會給一些項目提供共通的操作,因此你可能想要添加複選框或類似的允許使用者選擇項目的UI元素,因為它們可能沒有長按事件行為,所以在使用者選擇複選框時,你能夠通過設定各自清單項目的複選狀態的setItemChecked()方法來調用上下文操作模式。