天天看點

android的上下文菜單和上下文操作模式

例如長按删除功能就是一種上下文操作,上下文操作與某個特定的螢幕視圖(單個清單項)而非整個螢幕相關聯

一:在res/menu下建立菜單資源檔案

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/menu_item_delete_crime"
        android:icon="@android:drawable/ic_menu_delete"
        android:title="@string/delete_crime"
        ></item>

</menu>
           

二:建立上下文菜單和響應

onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo)建立

onContextItemSelected(MenuItem item)響應

建立上下文菜單:

@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		getActivity().getMenuInflater().inflate(R.menu.crime_list_item_context, menu);
		
	}
           

預設情況下,長按視圖不會觸發上下文菜單的建立,要觸發上下文菜單的建立,就要在onCreateView中調用Fragment的registerForContextMenu(View view)登記一個視圖

ListView listView = (ListView) v.findViewById(android.R.id.list);
registerForContextMenu(listView);
           

響應上下文菜單選擇

調用onContextItemSelected(MenuItem item),并在方法中編寫響應邏輯,例如我要進行删除

@Override
	public boolean onContextItemSelected(MenuItem item){
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
	    int position = info.position;
	    CrimeAdapter adapter = (CrimeAdapter) getListAdapter();
	    Crime crime = adapter.getItem(position);
	    
	    switch (item.getItemId()) {
		case R.id.menu_item_delete_crime:
			CrimeLab.get(getActivity()).delete(crime);
			adapter.notifyDataSetChanged();
			return true;
		default:
			break;
		}
	    
		return super.onContextItemSelected(item);
	}
           

三:如果要實作清單視圖的多選操作(例如長按可以選多多個item删除)

1.在onCreateView中設定清單視圖的選擇模式為CHOICE_MODE_MULTIPLE_MODAL

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
           

此時已經實作了清單視圖的多選模式了

2.清單視圖的操作模式回調方法

listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
				
				@Override
				public void onItemCheckedStateChanged(ActionMode mode, int position,
						long id, boolean checked) {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public boolean onCreateActionMode(ActionMode mode, Menu menu) {
					// TODO Auto-generated method stub
					MenuInflater inflater = mode.getMenuInflater();
					inflater.inflate(R.menu.crime_list_item_context, menu);
					return true;
				}
				
				@Override
				public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
					// TODO Auto-generated method stub
					return false;
				}
				
				@Override
				public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
					switch (item.getItemId()) {
					case R.id.menu_item_delete_crime:
						CrimeAdapter adapter = (CrimeAdapter) getListAdapter();
						CrimeLab crimeLab = CrimeLab.get(getActivity());
						for(int i = adapter.getCount() - 1; i >= 0; i--){
							if(getListView().isItemChecked(i)){
								crimeLab.delete(adapter.getItem(i));
							}
						}
						mode.finish();
						adapter.notifyDataSetChanged();
						return true;

					default:
						return false;
					}
				}
				
				@Override
				public void onDestroyActionMode(ActionMode mode) {
					// TODO Auto-generated method stub
					
				}
	
			});
           

為視圖實作AbsListView.MultiChoiceModeListener接口的監聽器,該接口包含onItemCheckedStateChanged(Action mode, int position, long id, boolean checked)這個方法,每當視圖被選中或者撤銷的都會觸發此方法,但由于AbsListView.MultiChoiceModeListener接口包含了ActionMode.callback接口,是以還要實作一下幾個方法:

1.public abstract boolean onCreateActionMode(ActionMode mode, Menu menu)

在ActionMode對象建立後使用,執行個體化菜單并顯示在上下文操作欄的地方

2.public boolean onPrepareActionMode(ActionMode mode, Menu menu)

上下文需要重新整理顯示新資料時調用

3.public boolean onActionItemClicked(ActionMode mode, MenuItem item)

使用者選中某個菜單項操作時調用,響應上下文菜單操作的地方

4.public void onDestroyActionMode(ActionMode mode)

一般在actionmode銷毀時選用

四:此時可以實作多選操作了,但是長按已選背景并沒有改變,導緻使用者不能區分

首先,在res/drawable目錄下建立background_activated.xml檔案

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:state_activated="true"
        android:drawable="@android:color/darker_gray">
        
    </item>

</selector>
           

state_activated為true,表明當引用該資源的視圖(此處為listview)處于激活狀态時,則使用android:drawable屬性所指定的資源。

如果為false,則隻要視圖處于未被激活時,android:drawable屬性所指定的資源都會被使用

然後在原來視圖(此處為listview)加上屬性android:background="@drawable/background_activated"

此時長按清單項,被選中的listItem就會顯示darker_gray的顔色

思考:

以上所說的上下文操作欄可以完美得應用于ListView和GirdView,但是對于其它視圖,是不支援的。

對于其他視圖,我們首先設定一個實作View.OnLongClickListener接口的監聽器,然後在監聽器體内,調用Activity的startActionMode()建立一個actionMode執行個體,MultiChoiceModeListener接口中的ActionMode執行個體是自動建立的,startActionMode()需要一個實作ActionMode.callBack接口對象作為參數,是以建立一個ActionMode.callBack接口的實作,自然也要實作那四個方法:

1.public abstract boolean onCreateActionMode(ActionMode mode, Menu menu)

2.public boolean onPrepareActionMode(ActionMode mode, Menu menu)

3.public boolean onActionItemClicked(ActionMode mode, MenuItem item)

4.public void onDestroyActionMode(ActionMode mode)