Android的menu有多种实现方式,Action Mode是Android 3.0以后出现的,我们可以使用AppCompat库使Action Mode兼容至Android 2.1。
Android 3.0以前,我们处理列表的长按事件经常使用Context Menu,Android3.0以后,我们有了新的选择:Action Mode。下图左边效果为Context Menu右边效果为Action Mode。
Android开发者应该都熟悉Context Menu了,Context Menu是悬浮在操作项之上的视图。Action Mode是临时占据了ActionBar的位置。
关于Action Mode 详细资料:http://developer.android.com/guide/topics/ui/menus.html#context-menu
自己写了一个示例以增强记忆运行效果如下:
在TextView上使用Contextual Action Mode
在ListView上使用Contextual Action Mode
1、在单个View上使用Contextual Action Mode
package com.example.cabtest;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class IndividualviewsCAMActivity extends Activity {
private ActionMode mActionMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_individual);
super.onCreate(savedInstanceState);
ActionBar mActionBar = getActionBar();
mActionBar.setDisplayHomeAsUpEnabled(true);
mActionBar.setDisplayUseLogoEnabled(true);
findView();
}
@SuppressLint("NewApi")
private void findView() {
String content = "北京时间12月5日消息,据国外科技网站BusinessInsider报道,日前,美国麻省理工学院(MIT)有形媒体小组的一个研究团队研发出了一种新的人机交互技术——人类可以进入电脑进行远程的物理操作。该技术现在只能模拟非常基本的动作,比如击掌或是来回拍球。而在未来,一个更复杂的版本或许能够在更大的屏幕上工作,并重现整个人体。";
TextView tv_content = (TextView) findViewById(R.id.tv_content);
tv_content.setText(content);
tv_content.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mActionMode != null) {
return false;
}
mActionMode = IndividualviewsCAMActivity.this
.startActionMode(mActionModeCallback);
v.setSelected(true);
return true;
}
});
}
@SuppressLint("NewApi")
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@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_individual, 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_copy:
Toast.makeText(getApplicationContext(), R.string.menu_copy,
Toast.LENGTH_SHORT).show();
mode.finish(); // Action picked, so close the CAB
return true;
case R.id.menu_delete:
Toast.makeText(getApplicationContext(), R.string.menu_delete,
Toast.LENGTH_SHORT).show();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.context_menu_test, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
context_menu_individual.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_copy"
android:icon="@drawable/ic_copy"
android:orderInCategory="1"
android:showAsAction="always"
android:title="@string/menu_copy"/>
<item
android:id="@+id/menu_delete"
android:icon="@drawable/ic_delete"
android:orderInCategory="2"
android:showAsAction="always"
android:title="@string/menu_delete"/>
</menu>
2、在ListView/GridView 上使用Contextual Action Mode
package com.example.cabtest;
import java.util.ArrayList;
import java.util.List;
import com.example.cabtest.entity.Book;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ListCAMActivity extends Activity {
private List<Book> mList = new ArrayList<Book>();
private List<Book> checkedList = new ArrayList<Book>();
private BookAdapter mAdapter;
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_list);
super.onCreate(savedInstanceState);
ActionBar mActionBar = getActionBar();
mActionBar.setDisplayHomeAsUpEnabled(true);
mActionBar.setDisplayUseLogoEnabled(true);
initData();
findView();
}
private void initData() {
for (int i = 0; i < 40; i++) {
Book book = new Book();
book.setId(i);
book.setName("Thinking In Java " + i);
mList.add(book);
}
}
private void findView() {
mListView = (ListView) findViewById(R.id.mListView);
mAdapter = new BookAdapter();
mListView.setAdapter(mAdapter);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListView.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
Book book = mList.get(position);
if (checked) {
book.setChecked(true);
checkedList.add(book);
} else {
checkedList.remove(book);
book.setChecked(false);
}
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
setSubtitle(mode);
}
private void setSubtitle(ActionMode mode) {
int checkedCount = checkedList.size();
// int checkedCount = mListView.getCheckedItemCount();
switch (checkedCount) {
case 0:
mode.setSubtitle(null);
break;
default:
mode.setSubtitle("选择了" + checkedCount + "项");
break;
}
}
@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:
mList.removeAll(checkedList);
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
Toast.makeText(getApplicationContext(),
R.string.menu_delete, Toast.LENGTH_SHORT).show();
checkedList.clear();
mode.finish(); // Action picked, so close the CAB
return true;
case R.id.menu_edit:
Toast.makeText(getApplicationContext(), R.string.menu_edit,
Toast.LENGTH_SHORT).show();
mode.finish(); // Action picked, so close the CAB
return true;
case R.id.menu_detail:
Toast.makeText(getApplicationContext(),
R.string.menu_detail, Toast.LENGTH_SHORT).show();
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_list, 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;
}
});
}
private class BookAdapter extends BaseAdapter {
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(getApplicationContext(),
R.layout.list_item, null);
holder = new ViewHolder();
holder.tv_name = (TextView) convertView
.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Book book = mList.get(position);
if(book.isChecked()){
convertView.setBackgroundColor(getResources().getColor(R.color.blur));
}else{
convertView.setBackgroundColor(getResources().getColor(R.color.white));
}
holder.tv_name.setText(book.getName());
return convertView;
}
}
static class ViewHolder {
TextView tv_name;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.context_menu_test, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
context_menu_list.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_delete"
android:icon="@drawable/ic_delete"
android:orderInCategory="1"
android:showAsAction="always"
android:title="@string/menu_delete"/>
<item
android:id="@+id/menu_edit"
android:icon="@drawable/ic_edit"
android:orderInCategory="2"
android:showAsAction="always"
android:title="@string/menu_edit"/>
<item
android:id="@+id/menu_detail"
android:icon="@drawable/ic_detail"
android:orderInCategory="3"
android:showAsAction="always"
android:title="@string/menu_detail"/>
</menu>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_gravity="center_vertical"
android:layout_margin="10dp"
android:textColor="@color/black"/>
</LinearLayout>
context_menu_test.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_refresh"
android:icon="@drawable/ic_action_refresh"
android:orderInCategory="1"
android:showAsAction="always"
android:title="@string/menu_refresh"/>
<item
android:id="@+id/menu_search"
android:icon="@drawable/ic_action_search"
android:orderInCategory="2"
android:showAsAction="always"
android:title="@string/menu_search"/>
</menu>