【凯子哥带你夯实应用层】使用ActionMode实现有删除动画的多选删除功能

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 

    ActionMode是3.0之后。官方推荐的一种上下文菜单的实现方式,在之前一直用的是Context Menu,今天这篇文章简介一下ActionMode,并实现多选删除功能。

    假设要在ListView这类控件中实现多选,我们能够通过设置setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL)来实现,然后通过设置setMultiChoiceModeListener之后,就能够开启ActionMode。

ActionMode并非一个View。仅仅是一个操作模式,所以我们用的时候不能依照View的使用方法来使用。

    以下是实现的效果图



    这个和GMail的删除是不是非常像?

    由于ActionMode没有多少知识点要说。咱们就简介下,然后上代码,这个功能主要事实上主要是逻辑麻烦点,也非常easy。

    设置完多选模式监听器之后,我们须要实现以下的方法

mListView.setMultiChoiceModeListener(new MultiChoiceModeListener(){

			@Override
			public boolean onCreateActionMode(ActionMode mode, Menu menu) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void onDestroyActionMode(ActionMode mode) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onItemCheckedStateChanged(ActionMode mode,
					int position, long id, boolean checked) {
				// TODO Auto-generated method stub
				
			}
			
		});

    就5个方法,看名字也非常好理解。

    在onCreateActionMode()中,一般实现ActionMode下右側的MenuItem配置。和标题设置。比方像以下这样

@Override
			public boolean onCreateActionMode(ActionMode mode, Menu menu) {
				// 在进入ActionMode的时候调用
				MenuInflater inflater = mode.getMenuInflater();
				inflater.inflate(R.menu.menu_delete, menu);
				mode.setTitle("Delete");
				isInActionMode = true;
				isInDeleteMode = false;

				return true;
			}

    onActionItemClicked则是在我们设置的MenuItem点击之后调用,和ActionBar里面的MenuItem一样。所以我们能够像以下这样

@Override
			public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

				// 当listview中的item被点击的时候调用
				if (item.getItemId() == R.id.action_delete) {
					mAnimateDismissAdapter.animateDismiss(mCheckedPositions);
					isInDeleteMode = true;
					mode.finish();
					return true;
				}

				return false;
			}

    onItemCheckedStateChanged则是我们的listview的item点击的时候调用,我们能够依据position和checked进行逻辑操作。

    基本这几个方法就基本满足我们的功能了,以下是完整的演示样例代码

package com.imooc.multychoice;

import java.util.ArrayList;
import java.util.Iterator;

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.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

import com.haarman.listviewanimations.itemmanipulation.AnimateDismissAdapter;
import com.haarman.listviewanimations.itemmanipulation.OnDismissCallback;
import com.imooc.multychoice.R;

public class MainActivity extends Activity {

	protected static final String TAG = "TAG";
	private ListView mListView;
	private MultyAdapter mAdapter;
	// 是否处于ActionMode模式
	private boolean isInActionMode;
	private boolean isInDeleteMode = false;
	private AnimateDismissAdapter<Model> mAnimateDismissAdapter;
	private ArrayList<Integer> mCheckedPositions;

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

		mListView = (ListView) findViewById(R.id.lv);
		mAdapter = new MultyAdapter();
		mCheckedPositions = new ArrayList<Integer>();

		mAnimateDismissAdapter = new AnimateDismissAdapter<MainActivity.Model>(
				mAdapter, new MyDismissCallBack());
		mAnimateDismissAdapter.setAbsListView(mListView);
		mListView.setAdapter(mAnimateDismissAdapter);

		mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);

		mListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

			@Override
			public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
				return false;
			}

			@Override
			public void onDestroyActionMode(ActionMode mode) {

				// 在退出ActionMode的时候调用。假设处于删除状态。就删除选中的数据,
				// 否则,重置全部选中的状态
				if (!isInDeleteMode) {
					for (Model model : mAdapter.models) {
						model.setChecked(false);
					}
					mCheckedPositions.clear();
				}

				isInActionMode = false;

			}

			@Override
			public boolean onCreateActionMode(ActionMode mode, Menu menu) {
				// 在进入ActionMode的时候调用
				MenuInflater inflater = mode.getMenuInflater();
				inflater.inflate(R.menu.menu_delete, menu);
				mode.setTitle("Delete");
				isInActionMode = true;
				isInDeleteMode = false;

				return true;
			}

			@Override
			public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

				// 当listview中的item被点击的时候调用
				if (item.getItemId() == R.id.action_delete) {
					mAnimateDismissAdapter.animateDismiss(mCheckedPositions);
					isInDeleteMode = true;
					mode.finish();
					return true;
				}

				return false;
			}

			@Override
			public void onItemCheckedStateChanged(ActionMode mode,
					int position, long id, boolean checked) {

				// 当item的选中状态被选中的时候调用
				mAdapter.models.get(position).setChecked(checked);
				mAdapter.notifyDataSetChanged();
				mode.setSubtitle(mListView.getCheckedItemCount()
						+ " item selected");

				if (mCheckedPositions.contains(position) && !checked) {
					mCheckedPositions.remove(Integer.valueOf(position));
				} else {
					mCheckedPositions.add(position);
				}

			}
		});

	}

	private class MultyAdapter extends BaseAdapter {

		private ArrayList<Model> models;

		public MultyAdapter() {

			models = new ArrayList<Model>();
			for (int i = 0; i < 20; i++) {
				models.add(new Model("I'm " + i));
			}

		}

		@Override
		public int getCount() {
			return models.size();
		}

		@Override
		public Model getItem(int position) {
			return models.get(position);
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			ViewHolder viewHolder;

			Model model = mAdapter.models.get(position);

			if (convertView == null) {

				convertView = getLayoutInflater().inflate(
						R.layout.item_multy_choice, parent, false);

				viewHolder = new ViewHolder();

				viewHolder.tv = (TextView) convertView.findViewById(R.id.tv);
				viewHolder.chb = (CheckBox) convertView.findViewById(R.id.chb);
				convertView.setTag(viewHolder);
			} else {
				viewHolder = (ViewHolder) convertView.getTag();
			}

			viewHolder.tv.setText(model.getTitle());
			viewHolder.chb.setChecked(model.isChecked());
			viewHolder.chb.setVisibility(isInActionMode ? View.VISIBLE
					: View.GONE);

			return convertView;
		}
	}

	private static class ViewHolder {
		TextView tv;
		CheckBox chb;
	}

	/**
	 * 測试Model
	 * 
	 * @author zhaokaiqiang
	 * 
	 */
	private class Model {

		private String title;

		private boolean isChecked;

		public Model(String title) {
			this.title = title;
			isChecked = false;
		}

		public String getTitle() {
			return title;
		}

		public boolean isChecked() {
			return isChecked;
		}

		public void setChecked(boolean isChecked) {
			this.isChecked = isChecked;
		}

	}

	private class MyDismissCallBack implements OnDismissCallback {

		@Override
		public void onDismiss(AbsListView arg0, int[] arg1) {

			mCheckedPositions.clear();

			Iterator<Model> iterator = mAdapter.models.iterator();
			while (iterator.hasNext()) {
				if (iterator.next().isChecked()) {
					// 删除选中的元素
					iterator.remove();
				}
			}
			mAdapter.notifyDataSetChanged();
		}
	}

}

    在上面的代码中。为了实现动画效果,我使用了开源项目ListViewAnimation中的AnimationDismissAdapter。详细使用方法非常easy。直接看代码就能够啦~


    下载地址:https://github.com/ZhaoKaiQiang/MultyChoiceDemo

posted @ 2018-04-22 14:33  llguanli  阅读(282)  评论(0编辑  收藏  举报