【凱子哥帶你夯實應用層】使用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沒有多少知識點要說,咱們就簡單介紹下,然後上代碼,這個功能主要其實主要是邏輯麻煩點,也很簡單。

    設置完多選模式監聽器之後,我們需要實現下面的方法

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,具體用法很簡單,直接看代碼就可以啦~


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

發佈了130 篇原創文章 · 獲贊 129 · 訪問量 148萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章