【凯子哥带你夯实应用层】使用ActionMode实现有删除动画的多选删除功能
转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992
ActionMode是3.0之后。官方推荐的一种上下文菜单的实现方式,在之前一直用的是Context Menu,今天这篇文章简介一下ActionMode,并实现多选删除功能。
假设要在ListView这类控件中实现多选,我们能够通过设置setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL)来实现,然后通过设置setMultiChoiceModeListener之后,就能够开启ActionMode。
ActionMode并非一个View。仅仅是一个操作模式,所以我们用的时候不能依照View的使用方法来使用。
以下是实现的效果图
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhb2thaXFpYW5nMTk5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
这个和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。直接看代码就能够啦~
【凯子哥带你夯实应用层】使用ActionMode实现有删除动画的多选删除功能的更多相关文章
- 【凯子哥带你夯实应用层】使用ActionProvider实现子菜单时遇到的一个坑
转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 近期在重温Android基础.在看到ActionProvider的时候遇到一个坑.分享到大家,避免入坑. 首 ...
- 【凯子哥带你学Framework】Activity启动过程全解析
It’s right time to learn Android’s Framework ! 前言 学习目标 写作方式 主要对象功能介绍 主要流程介绍 zygote是什么有什么作用 SystemSer ...
- 【凯子哥带你学Framework】Activity界面显示全解析(下)
咱们接着上篇继续讲,上篇没看的请戳:[凯子哥带你学Framework]Activity界面显示全解析(上) 如何验证上一个问题 首先,说明一下运行条件: //主题 name="AppThem ...
- 【转载】【凯子哥带你学Framework】Activity启动过程全解析
It's right time to learn Android's Framework ! 前言 一个App是怎么启动起来的? App的程序入口到底是哪里? Launcher到底是什么神奇的东西? ...
- 【凯子哥带你学Framework】Activity界面显示全解析
前几天凯子哥写的Framework层的解析文章<Activity启动过程全解析>,反响还不错,这说明“写让大家都能看懂的Framework解析文章”的思想是基本正确的. 我个人觉得,深入分 ...
- 【转载】【凯子哥带你学Framework】Activity界面显示全解析(下)
如何验证上一个问题 首先,说明一下运行条件 //主题 name="AppTheme" parent="@android:style/Theme.Holo.Light.No ...
- 凯哥带你用python撸算法之雪花算法
import time class Snow(object): def __init__(self, idx=None): init_date = time.strptime('2010-01-01 ...
- mysql 数据操作 多表查询 子查询 带IN关键字的子查询
1 带IN关键字的子查询 #查询平均年龄在25岁以上的部门名关键点部门名 以查询员工表的dep_id的结果 当作另外一条sql语句查询条件使用 in (sql语句) mysql ; +-------- ...
- mysql 数据操作 多表查询 子查询 带比较运算符的子查询
带比较运算符的子查询 #比较运算符:=.!=.>.>=.<.<=.<> #查询大于所有人平均年龄的员工名与年龄 思路 先拿到所有人的平均年龄然后 再用另外一条sql ...
随机推荐
- 使用influx控制台工具操作InfluxDB
这里记录下influx控制台的简单使用,如需更多功能请参考InfluxDB官方文档: https://docs.influxdata.com/influxdb/v1.1/ 环境: CentOS6.5_ ...
- ssh出错 sign_and_send_pubkey: signing failed: agent refused operation
在服务器添加完公钥之后,ssh服务器然后报了这个错误 sign_and_send_pubkey: signing failed: agent refused operation 然后执行了以下命令才好 ...
- dubbo高级配置学习(上)
启动时检查 Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认check=true. 如果你的Spring容器是懒加载的, ...
- 完美解决office2013 错误1402
遇到1402问题 按照网络上的帖子都无法解决,老提示无权限更改,原来只是少了一个步骤而已!经本人多次试验,已经完美解决,现在上图! 步骤 肯定是得先出现错误,找到注册表所在项! 这个就不赘述,通过 ...
- DUBBO本地搭建及小案例 (转)
DUBBO的介绍部分我这里就不介绍了,大家可参考官方文档. DUBBO的注册中心安装 DUBBO的注册中心支持好几种,公司用到zookeeper注册中心,所以我这边只说明zookeeper注册中心如何 ...
- NFC手机上基于软件的卡模拟 重大利好还是安全噩梦?(转)
Software Card Emulation in NFC-enabled Mobile Phones: GreatAdvantage or Security Nightmare? Michael ...
- ID3D11DeviceContext::DrawIndexed DrawIndexed 参数详解 StartIndexLocation BaseVertexLocation
先来看一下画的结果: m_pImmediateContext->DrawIndexed(36, 0, 0); 这个是画一个立方体 后两个参数都是0没有什么可说的. m_pImmediateCon ...
- vscode用法
工欲善其事,必先利其器.vscode是一个值得花费时间去掌握精通的编辑器. 好文档不必远求 打开vscode,把菜单看上三遍,仔细思考每个菜单项的作用,思考为啥要这样归类每个菜单项. 配置是系统的核心 ...
- javascript中的复制
github 深度复制这个问题看似简单,实际上要想完美实现需要很多知识. 需要考虑Set,Map,Promise等类型的对象 这个库简洁明了,是一个小巧玲珑的JS库 Promise简单例子 funct ...
- OAuth的机制原理讲解及开发流程(转)
1.OAuth的简述 OAuth(Open Authorization,开放授权)是为用户资源的授权定义了一个安全.开放及简单的标准,第三方无需知道用户的账号及密码,就可获取到用户的授权信息,并且这是 ...