当前位置: 首页 > news >正文

【凯子哥带你夯实应用层】使用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

相关文章:

  • Purism发布Librem 5 Linux手机文档
  • centos7 安装 elasticsearch-6.2.4
  • Kubernetes 1.10和Cross-Cloud CI Project Dashboard 1.3释放,Kubernetes发布用户调查
  • 【大数据】数据的优美
  • JAVA——泛型类和泛型方法(静态方法泛型)
  • oracle修改某个表的字段顺序
  • 令牌桶算法限流
  • nginx的ngx_module_s 模块
  • 阿里云RDS-MYSQL数据库参数设置
  • k8s实验环境的快速搭建
  • IBM欲寻找量子杀手级应用
  • jQuery插件 -- Form表单插件jquery.form.js
  • 日志框架 - 基于spring-boot - 实现2 - 消息定义及消息日志打印
  • php命令行生成项目结构
  • P4035 [JSOI2008]球形空间产生器
  • 【刷算法】求1+2+3+...+n
  • 2017-08-04 前端日报
  • CentOS 7 修改主机名
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • es6
  • es的写入过程
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Flannel解读
  • git 常用命令
  • Javascript弹出层-初探
  • JavaScript设计模式之工厂模式
  • JS基础之数据类型、对象、原型、原型链、继承
  • MobX
  • mysql 5.6 原生Online DDL解析
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Vue.js 移动端适配之 vw 解决方案
  • 大型网站性能监测、分析与优化常见问题QA
  • 分类模型——Logistics Regression
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 前端路由实现-history
  • 前端相关框架总和
  • 使用parted解决大于2T的磁盘分区
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 小程序01:wepy框架整合iview webapp UI
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 再次简单明了总结flex布局,一看就懂...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • #pragma pack(1)
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (1)常见O(n^2)排序算法解析
  • (13):Silverlight 2 数据与通信之WebRequest
  • (AngularJS)Angular 控制器之间通信初探
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (c语言)strcpy函数用法
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (南京观海微电子)——COF介绍
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)C#开发微信门户及应用(1)--开始使用微信接口