使用ActionMode实现有删除动画的多选删除功能

来源:互联网 发布:博思数据 电子烟 编辑:程序博客网 时间:2024/06/07 03:44


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

    如果要在ListView这类控件中实现多选,我们可以通过设置setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL)来实现,然后通过设置setMultiChoiceModeListener之后,就可以开启ActionMode。ActionMode并不是一个View,只是一个操作模式,所以我们用的时候不能按照View的用法来使用。

    下面是实现的效果图



    这个和GMail的删除是不是很像?

    因为ActionMode没有多少知识点要说,咱们就简单介绍下,然后上代码,这个功能主要其实主要是逻辑麻烦点,也很简单。

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. mListView.setMultiChoiceModeListener(new MultiChoiceModeListener(){  
  2.   
  3.             @Override  
  4.             public boolean onCreateActionMode(ActionMode mode, Menu menu) {  
  5.                 // TODO Auto-generated method stub  
  6.                 return false;  
  7.             }  
  8.   
  9.             @Override  
  10.             public boolean onPrepareActionMode(ActionMode mode, Menu menu) {  
  11.                 // TODO Auto-generated method stub  
  12.                 return false;  
  13.             }  
  14.   
  15.             @Override  
  16.             public boolean onActionItemClicked(ActionMode mode, MenuItem item) {  
  17.                 // TODO Auto-generated method stub  
  18.                 return false;  
  19.             }  
  20.   
  21.             @Override  
  22.             public void onDestroyActionMode(ActionMode mode) {  
  23.                 // TODO Auto-generated method stub  
  24.                   
  25.             }  
  26.   
  27.             @Override  
  28.             public void onItemCheckedStateChanged(ActionMode mode,  
  29.                     int position, long id, boolean checked) {  
  30.                 // TODO Auto-generated method stub  
  31.                   
  32.             }  
  33.               
  34.         });  

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

    在onCreateActionMode()中,一般实现ActionMode下右侧的MenuItem配置,和标题设置,比如像下面这样

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.             public boolean onCreateActionMode(ActionMode mode, Menu menu) {  
  3.                 // 在进入ActionMode的时候调用  
  4.                 MenuInflater inflater = mode.getMenuInflater();  
  5.                 inflater.inflate(R.menu.menu_delete, menu);  
  6.                 mode.setTitle("Delete");  
  7.                 isInActionMode = true;  
  8.                 isInDeleteMode = false;  
  9.   
  10.                 return true;  
  11.             }  

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.             public boolean onActionItemClicked(ActionMode mode, MenuItem item) {  
  3.   
  4.                 // 当listview中的item被点击的时候调用  
  5.                 if (item.getItemId() == R.id.action_delete) {  
  6.                     mAnimateDismissAdapter.animateDismiss(mCheckedPositions);  
  7.                     isInDeleteMode = true;  
  8.                     mode.finish();  
  9.                     return true;  
  10.                 }  
  11.   
  12.                 return false;  
  13.             }  

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

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.imooc.multychoice;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Iterator;  
  5.   
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.view.ActionMode;  
  9. import android.view.Menu;  
  10. import android.view.MenuInflater;  
  11. import android.view.MenuItem;  
  12. import android.view.View;  
  13. import android.view.ViewGroup;  
  14. import android.widget.AbsListView;  
  15. import android.widget.AbsListView.MultiChoiceModeListener;  
  16. import android.widget.BaseAdapter;  
  17. import android.widget.CheckBox;  
  18. import android.widget.ListView;  
  19. import android.widget.TextView;  
  20.   
  21. import com.haarman.listviewanimations.itemmanipulation.AnimateDismissAdapter;  
  22. import com.haarman.listviewanimations.itemmanipulation.OnDismissCallback;  
  23. import com.imooc.multychoice.R;  
  24.   
  25. public class MainActivity extends Activity {  
  26.   
  27.     protected static final String TAG = "TAG";  
  28.     private ListView mListView;  
  29.     private MultyAdapter mAdapter;  
  30.     // 是否处于ActionMode模式  
  31.     private boolean isInActionMode;  
  32.     private boolean isInDeleteMode = false;  
  33.     private AnimateDismissAdapter<Model> mAnimateDismissAdapter;  
  34.     private ArrayList<Integer> mCheckedPositions;  
  35.   
  36.     @Override  
  37.     protected void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.         setContentView(R.layout.activity_main);  
  40.   
  41.         mListView = (ListView) findViewById(R.id.lv);  
  42.         mAdapter = new MultyAdapter();  
  43.         mCheckedPositions = new ArrayList<Integer>();  
  44.   
  45.         mAnimateDismissAdapter = new AnimateDismissAdapter<MainActivity.Model>(  
  46.                 mAdapter, new MyDismissCallBack());  
  47.         mAnimateDismissAdapter.setAbsListView(mListView);  
  48.         mListView.setAdapter(mAnimateDismissAdapter);  
  49.   
  50.         mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);  
  51.   
  52.         mListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {  
  53.   
  54.             @Override  
  55.             public boolean onPrepareActionMode(ActionMode mode, Menu menu) {  
  56.                 return false;  
  57.             }  
  58.   
  59.             @Override  
  60.             public void onDestroyActionMode(ActionMode mode) {  
  61.   
  62.                 // 在退出ActionMode的时候调用,如果处于删除状态,就删除选中的数据,  
  63.                 // 否则,重置所有选中的状态  
  64.                 if (!isInDeleteMode) {  
  65.                     for (Model model : mAdapter.models) {  
  66.                         model.setChecked(false);  
  67.                     }  
  68.                     mCheckedPositions.clear();  
  69.                 }  
  70.   
  71.                 isInActionMode = false;  
  72.   
  73.             }  
  74.   
  75.             @Override  
  76.             public boolean onCreateActionMode(ActionMode mode, Menu menu) {  
  77.                 // 在进入ActionMode的时候调用  
  78.                 MenuInflater inflater = mode.getMenuInflater();  
  79.                 inflater.inflate(R.menu.menu_delete, menu);  
  80.                 mode.setTitle("Delete");  
  81.                 isInActionMode = true;  
  82.                 isInDeleteMode = false;  
  83.   
  84.                 return true;  
  85.             }  
  86.   
  87.             @Override  
  88.             public boolean onActionItemClicked(ActionMode mode, MenuItem item) {  
  89.   
  90.                 // 当listview中的item被点击的时候调用  
  91.                 if (item.getItemId() == R.id.action_delete) {  
  92.                     mAnimateDismissAdapter.animateDismiss(mCheckedPositions);  
  93.                     isInDeleteMode = true;  
  94.                     mode.finish();  
  95.                     return true;  
  96.                 }  
  97.   
  98.                 return false;  
  99.             }  
  100.   
  101.             @Override  
  102.             public void onItemCheckedStateChanged(ActionMode mode,  
  103.                     int position, long id, boolean checked) {  
  104.   
  105.                 // 当item的选中状态被选中的时候调用  
  106.                 mAdapter.models.get(position).setChecked(checked);  
  107.                 mAdapter.notifyDataSetChanged();  
  108.                 mode.setSubtitle(mListView.getCheckedItemCount()  
  109.                         + " item selected");  
  110.   
  111.                 if (mCheckedPositions.contains(position) && !checked) {  
  112.                     mCheckedPositions.remove(Integer.valueOf(position));  
  113.                 } else {  
  114.                     mCheckedPositions.add(position);  
  115.                 }  
  116.   
  117.             }  
  118.         });  
  119.   
  120.     }  
  121.   
  122.     private class MultyAdapter extends BaseAdapter {  
  123.   
  124.         private ArrayList<Model> models;  
  125.   
  126.         public MultyAdapter() {  
  127.   
  128.             models = new ArrayList<Model>();  
  129.             for (int i = 0; i < 20; i++) {  
  130.                 models.add(new Model("I'm " + i));  
  131.             }  
  132.   
  133.         }  
  134.   
  135.         @Override  
  136.         public int getCount() {  
  137.             return models.size();  
  138.         }  
  139.   
  140.         @Override  
  141.         public Model getItem(int position) {  
  142.             return models.get(position);  
  143.         }  
  144.   
  145.         @Override  
  146.         public long getItemId(int position) {  
  147.             return 0;  
  148.         }  
  149.   
  150.         @Override  
  151.         public View getView(int position, View convertView, ViewGroup parent) {  
  152.   
  153.             ViewHolder viewHolder;  
  154.   
  155.             Model model = mAdapter.models.get(position);  
  156.   
  157.             if (convertView == null) {  
  158.   
  159.                 convertView = getLayoutInflater().inflate(  
  160.                         R.layout.item_multy_choice, parent, false);  
  161.   
  162.                 viewHolder = new ViewHolder();  
  163.   
  164.                 viewHolder.tv = (TextView) convertView.findViewById(R.id.tv);  
  165.                 viewHolder.chb = (CheckBox) convertView.findViewById(R.id.chb);  
  166.                 convertView.setTag(viewHolder);  
  167.             } else {  
  168.                 viewHolder = (ViewHolder) convertView.getTag();  
  169.             }  
  170.   
  171.             viewHolder.tv.setText(model.getTitle());  
  172.             viewHolder.chb.setChecked(model.isChecked());  
  173.             viewHolder.chb.setVisibility(isInActionMode ? View.VISIBLE  
  174.                     : View.GONE);  
  175.   
  176.             return convertView;  
  177.         }  
  178.     }  
  179.   
  180.     private static class ViewHolder {  
  181.         TextView tv;  
  182.         CheckBox chb;  
  183.     }  
  184.   
  185.     /** 
  186.      * 测试Model 
  187.      *  
  188.      * @author zhaokaiqiang 
  189.      *  
  190.      */  
  191.     private class Model {  
  192.   
  193.         private String title;  
  194.   
  195.         private boolean isChecked;  
  196.   
  197.         public Model(String title) {  
  198.             this.title = title;  
  199.             isChecked = false;  
  200.         }  
  201.   
  202.         public String getTitle() {  
  203.             return title;  
  204.         }  
  205.   
  206.         public boolean isChecked() {  
  207.             return isChecked;  
  208.         }  
  209.   
  210.         public void setChecked(boolean isChecked) {  
  211.             this.isChecked = isChecked;  
  212.         }  
  213.   
  214.     }  
  215.   
  216.     private class MyDismissCallBack implements OnDismissCallback {  
  217.   
  218.         @Override  
  219.         public void onDismiss(AbsListView arg0, int[] arg1) {  
  220.   
  221.             mCheckedPositions.clear();  
  222.   
  223.             Iterator<Model> iterator = mAdapter.models.iterator();  
  224.             while (iterator.hasNext()) {  
  225.                 if (iterator.next().isChecked()) {  
  226.                     // 删除选中的元素  
  227.                     iterator.remove();  
  228.                 }  
  229.             }  
  230.             mAdapter.notifyDataSetChanged();  
  231.         }  
  232.     }  
  233.   
  234. }  

    在上面的代码中,为了实现动画效果,我使用了开源项目ListViewAnimation中的AnimationDismissAdapter,具体用法很简单,直接看代码就可以啦~


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


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

0 0