Android Contextual Menus之二:contextual action mode

Contextual action mode

  Contextual action mode是 ActionMode 的系统实现,关注于执行上下文相关动作的用户交互。

  当用户通过选择一个项目使能这个模式,一个contextual action bar就会出现在屏幕上方,显示用户对当前选中的项目可以执行的动作。

  当这个模式使能时,用户可以:选择多个项目(如果你允许的话)、取消项目选择、在activity中继续浏览(只要你允许)。

  当用户取消对所有项目的选择、按下Back键、或者点击bar左边的完成按钮之后,action mode就被禁用,contextual action bar消失。

  注意:contextual action bar没有必须 action bar关联,它们是独立的。

 

CAB的使用情形

  对于提供上下文动作的View,通常在这两种情况下(情况之一或both)调用contextual action mode

  1.用户在View上长按;

  2.用户选择了View中的CheckBox或者类似控件。

  你的应用如何invoke这个contextual action mode,以及如何定义每个action取决于你自己的设计。

  两种基本的设计:

  1.对个体任意views的上下文相关操作;

  For contextual actions on individual, arbitrary views.

  2.对一组数据的批处理,比如ListView或GridView中的项目,允许用户选择多个项目然后对它们整体执行一个动作。

  For batch contextual actions on groups of items in a ListView or GridView (allowing the user to select multiple items and perform an action on them all).

 

  下面分别讲讲这两种情景下的实现。

 

Enabling the contextual action mode for individual views

  如果你想在用户选择指定View的时候invoke contextual action mode(CAB),你应该:

  1.实现ActionMode.Callback接口。

  在这个接口的回调方法中,你可以指定contextual action bar的动作,响应action items的点击事件,还有处理action mode的生命周期事件。

  2.当你想要show这个bar的时候(比如用户长按view的时候),调用 startActionMode()方法。

例子代码:

package com.example.mengdd.hellocontextmenu;

import android.app.Activity;
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 ContextualActionModeActivity extends Activity {

    private TextView mTextView = null;
    private ActionMode mActionMode = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contextual_action_mode);

        mTextView = (TextView) findViewById(R.id.textView2);
        mTextView.setOnLongClickListener(new OnLongClickListener() {

            @Override
            public boolean onLongClick(View view) {
                if (mActionMode != null) {
                    return false;
                }

                // Start the CAB using the ActionMode.Callback defined above
                mActionMode = startActionMode(mActionModeCallback);
                view.setSelected(true);
                return true;
            }
        });
    }

    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_menu1, 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.edit:

                showEditor();
                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;
        }
    };

    private void showEditor() {
        Toast.makeText(ContextualActionModeActivity.this, "edit",
                Toast.LENGTH_LONG).show();
    }
}

Enabling batch contextual actions in a ListView or GridView

  对于ListView和GridView这样的集合类,想让用户进行批处理操作,应该如下:

  1.实现 AbsListView.MultiChoiceModeListener接口,通过setMultiChoiceModeListener()方法把它set进集合类控件。

  在这个listener的回调方法中,你可以指定contextual action bar的动作,响应action item的点击事件,处理其他继承自ActionMode.Callback的回调。

  2.调用 setChoiceMode()方法,使用参数 CHOICE_MODE_MULTIPLE_MODAL 。

package com.example.demos;

import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.ListView;
import android.widget.Toast;

/**
 * This demo illustrates the use of CHOICE_MODE_MULTIPLE_MODAL, a.k.a. selection mode on ListView.
 */
public class MainActivity extends ListActivity {
	
	protected static final String TAG = "yxf";
	private String[] mStrings = Cheeses.sCheeseStrings;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ListView lv = getListView();
        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        lv.setMultiChoiceModeListener(mMultiListener);
        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_checked, mStrings));
    }
    
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        getActionBar().setSubtitle("Long press to start selection");
    }
    
    private MultiChoiceModeListener mMultiListener = new MultiChoiceModeListener() {
        
    	  @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    		Log.d(TAG,"onCreateActionMode");
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.list_select_menu, menu);
            mode.setTitle("Select Items");
            setSubtitle(mode);
            return true;
        }

        /*Here you can perform updates to the CAB due to an invalidate() request. */
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        	Log.d(TAG,"onPrepareActionMode");
            return true;
        }

        /* 
         * 当用户选择一个上下文菜单项时被调用。
         */
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        	  Log.d(TAG,"onActionItemClicked");
        	  //Called when the user selects a contextual menu item.
            switch (item.getItemId()) {
            case R.id.share:
                Toast.makeText(MainActivity.this, "Shared " + getListView().getCheckedItemCount() +
                        " items", Toast.LENGTH_SHORT).show();
                mode.finish();
                break;
            default:
                Toast.makeText(MainActivity.this, "Clicked " + item.getTitle(),
                        Toast.LENGTH_SHORT).show();
                break;
            }
            return true;
        }

        //Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
        	Log.d(TAG,"onDestoryActionMode");
        }

        /**
         * 选中或者解除选中时调用,它监听的是listview中的某一项,处于选中状态则checked为true;处于解除状态则为 false。
         */
        @Override
        public void onItemCheckedStateChanged(ActionMode mode,
                int position, long id, boolean checked) {
        	Log.d(TAG,"onItemCheckedStateChanged,checked = " + checked);
        	/*
        	 * Here you can do something when items are selected/de-selected,
        	 * such as update the title in the CAB(Context Action Bar).
        	 */
            setSubtitle(mode);
        }

        private void setSubtitle(ActionMode mode) {
            final int checkedCount = getListView().getCheckedItemCount();
            switch (checkedCount) {
                case 0:
                    mode.setSubtitle(null);
                    break;
                case 1:
                    mode.setSubtitle("One item selected");
                    break;
                default:
                    mode.setSubtitle("" + checkedCount + " items selected");
                    break;
            }
        }
    };
    
}

class Cheeses {
    public static final String[] sCheeseStrings = {
            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale"
    };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值