actionmode与ActionBarSherlock:在2.x版本上使用Contextual Action Bar

Honeycomb 中引入的Contextual Action Bar(上下文actionbar) (CAB)是一种非常良好的设计。当ListView中有item被选中的时候,actionbar被出现的上下文菜单所替代,显得很智能化。但是这种效果只能在api11之后才能实现,这篇文章教你如何使用ActionBarSherlock的actionmode 以兼容更多的设备。

其实使用ActionBarSherlock来实现actionmode与原生sdk没有多大区别,最关键的地方是使用

SherlockListActivity和actionbarsherlock.view.ActionMode分别替代ListActivity以及android.view.ActionMode。

新建一个列表界面:

package fr.miximum.article;
import com.actionbarsherlock.app.SherlockListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ArticleActivity extends SherlockListActivity {
    static final String\[\] COUNTRIES = new String\[\] {
        "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
        "Angola", "Anguilla", "Canada", "France", "Spain" };
    private ListView mListView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mListView = getListView();
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        setListAdapter(new ArrayAdapter(this,
                android.R.layout.simple_list_item_multiple_choice, COUNTRIES));
    }
}

让我们来看看actionbarsherlock中actionmode是如何用的。

首先在menu资源文件中添加actionmode下的菜单选项,res/menu/contextual_actions.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/cab_action_delete"
        android:title="@string/action_delete"
        android:icon="@android:drawable/ic_menu_delete" />
</menu>

然后我们重新修改刚刚的ListActivity:

package fr.miximum.article;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import android.os.Bundle;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ArticleActivity extends SherlockListActivity  implements OnItemClickListener {
    static final String\[\] COUNTRIES = new String\[\] {
        "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
        "Angola", "Anguilla", "Canada", "France", "Spain" };
    private ListView mListView;
    private ActionMode mMode;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new ArrayAdapter(this,
                android.R.layout.simple_list_item_multiple_choice, COUNTRIES));
        mMode = null;
        mListView = getListView();
        mListView.setItemsCanFocus(false);
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        mListView.setOnItemClickListener(this);
    }
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // Notice how the ListView api is lame
        // You can use mListView.getCheckedItemIds() if the adapter
        // has stable ids, e.g you're using a CursorAdaptor
        SparseBooleanArray checked = mListView.getCheckedItemPositions();
        boolean hasCheckedElement = false;
        for (int i = 0 ; i < checked.size() && ! hasCheckedElement ; i++) {
            hasCheckedElement = checked.valueAt(i);
        }
        if (hasCheckedElement) {
            if (mMode == null) {
                mMode = startActionMode(new ModeCallback());
            }
        } else {
            if (mMode != null) {
                mMode.finish();
            }
        }
    };
    private final class ModeCallback implements ActionMode.Callback {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Create the menu from the xml file
            MenuInflater inflater = getSupportMenuInflater();
            inflater.inflate(R.menu.contextual_actions, menu);
            return true;
        }
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // Here, you can checked selected items to adapt available actions
            return false;
        }
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            // Destroying action mode, let's unselect all items
            for (int i = 0; i < mListView.getAdapter().getCount(); i++)
                mListView.setItemChecked(i, false);
            if (mode == mMode) {
                mMode = null;
            }
        }
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            long\[\] selected = mListView.getCheckedItemIds();
            if (selected.length > 0) {
                for (long id: selected) {
                    // Do something with the selected item
                }
            }
            mode.finish();
            return true;
        }
    };
}

你可以看到上面关于actionmode的api 和标准sdk中差不多。就是这么简单。