Android应用开发之多选删除之二
来源:互联网 发布:阎良广电网络怎么样 编辑:程序博客网 时间:2024/05/17 06:20
传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229
MultiSelectDeleteActivity.java
package cn.lynn.multisel;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.ContentUris;import android.content.Context;import android.content.DialogInterface;import android.database.Cursor;import android.net.Uri;import android.os.AsyncTask;import android.os.Bundle;import android.provider.ContactsContract.Contacts;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.CheckBox;import android.widget.ListView;import android.widget.TextView;public class MultiSelectDeleteActivity extends Activity implements OnClickListener, OnItemClickListener { private static final String TAG = "MultiSelectDeleteActivity"; private ListView delList; private Button delBtn; private Button canBtn; private CheckBox selAllChk; private Cursor cursor; private int count; private DeleteListAdapter delListAdapter; // 期望查询的联系人字段 private static final String[] PROJECTION = new String[] {Contacts._ID, Contacts.DISPLAY_NAME}; private static final int CONTACTS_ID_INDEX = 0; private static final int DISPLAY_NAME_INDEX = 1; // 用于保存记录是否被选中的状态,这里定义为静态变量是为了防止Home键切换之后普通成员变量无法保存切换之前的数据 private static HashMap<Integer, Boolean> statusMap; /** * 用于删除的联系人记录的封装类 */ private final class ViewHolder { TextView nameTxt; CheckBox selectChk; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); statusMap = new HashMap<Integer, Boolean>(); delList = (ListView) findViewById(R.id.del_list); delBtn = (Button) findViewById(R.id.del_btn); canBtn = (Button) findViewById(R.id.can_btn); selAllChk = (CheckBox) findViewById(R.id.select_all).findViewById(R.id.select_all_chk); delList.setOnItemClickListener(this); delBtn.setOnClickListener(this); canBtn.setOnClickListener(this); selAllChk.setOnClickListener(new SelectAllClickListener()); } @Override protected void onDestroy() { super.onDestroy(); statusMap.clear(); // 静态变量,提示和加快GC回收它,否则有很大可能要等到VM Full gc时才能回收 statusMap = null; } @Override public void onResume() { super.onResume(); refreshData(); } @Override protected void onPause() { super.onPause(); // 保存切换之前的记录数 count = cursor.getCount(); } /** * 查询联系人数据库记录 */ private void refreshData() { selAllChk.setEnabled(false); delBtn.setEnabled(false); cursor = getContentResolver().query(Contacts.CONTENT_URI, PROJECTION, null, null, null); if(cursor.getCount() > 0) { selAllChk.setEnabled(true); // Home键切换到Contacts应用增加联系人 if(count < cursor.getCount()) { selAllChk.setChecked(false); } } if(statusMap.containsValue(true)) { delBtn.setEnabled(true); } Log.i(TAG, "cursor= " + cursor); delListAdapter = new DeleteListAdapter(this, cursor); delList.setAdapter(delListAdapter); delListAdapter.notifyDataSetChanged(); } /** * 单独为全选CheckBox设置点击事件的监听器,因为它的布局是从当前Activity的子布局文件R.id.select_all中加载而来, * 这样做的好处是防止多个按钮都在Activity布局层次上监听同类点击事件时出现“屏蔽”现象 */ private class SelectAllClickListener implements OnClickListener { @Override public void onClick(View v) { if(selAllChk.isChecked()) { for (int i = 0; i < delListAdapter.getCount(); i++) { statusMap.put(i, true); delListAdapter.cursor.moveToPosition(i); delListAdapter.idSet.add(delListAdapter.cursor.getInt(CONTACTS_ID_INDEX) + ""); } delBtn.setEnabled(true); } else { for (int i = 0; i < delListAdapter.getCount(); i++) { statusMap.put(i, false); } delListAdapter.idSet.clear(); delBtn.setEnabled(false); } // 数据发生变化,通知UI更新 delListAdapter.notifyDataSetChanged(); } } /** * 为ListView设置删除联系人记录的Adapter */ private class DeleteListAdapter extends BaseAdapter { Cursor cursor; // 保存被选中的联系人Id HashSet<String> idSet; public DeleteListAdapter(Context context, Cursor cursor) { this.cursor = cursor; idSet = new HashSet<String>(); for (int i = 0; i < cursor.getCount(); i++) { // 初始化新的联系人记录为未选中的状态 if(statusMap.containsKey(i)) continue; statusMap.put(i, false); } Log.i(TAG, "statusMap size=" + statusMap.size()); } @Override public int getCount() { return cursor.getCount(); } @Override public Object getItem(int position) { if(cursor.moveToPosition(position)) { return cursor; } else { return null; } } @Override public long getItemId(int position) { return position; } // 这里启用了convertView缓存,并创建ViewHolder类以提高ListView执行效率 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null) { convertView = LayoutInflater.from(MultiSelectDeleteActivity.this).inflate(R.layout.list_item, null); holder = new ViewHolder(); holder.nameTxt = (TextView) convertView.findViewById(R.id.name_txt); holder.selectChk = (CheckBox) convertView.findViewById(R.id.select_chk); convertView.setTag(holder); } cursor.moveToPosition(position); holder = (ViewHolder) convertView.getTag(); final String name = cursor.getString(DISPLAY_NAME_INDEX); holder.nameTxt.setText(name); holder.selectChk.setChecked(statusMap.get(position)); if(statusMap.get(position)) { // 存储选中状态的记录的Id idSet.add(cursor.getInt(CONTACTS_ID_INDEX)+""); } else { // 移除非选中状态的记录的Id idSet.remove(cursor.getInt(CONTACTS_ID_INDEX)+""); } return convertView; } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Log.i(TAG, "onItemClick..."); ViewHolder holder = (ViewHolder) view.getTag(); holder.selectChk.toggle(); statusMap.put(position, holder.selectChk.isChecked()); delListAdapter.notifyDataSetChanged(); // 判断是否有记录没被选中,以便更改全选CheckBox的勾选状态 if(statusMap.containsValue(false)) { selAllChk.setChecked(false); } else { selAllChk.setChecked(true); } Log.i(TAG, "------------statusMap data--------------"); for (Map.Entry<Integer, Boolean> entry: statusMap.entrySet()) { Log.i(TAG, "statusMap key=" + entry.getKey() + ", value= " + entry.getValue()); } // 判断是否有记录被选中,以便更改删除Button的可用状态 if(statusMap.containsValue(true)) { delBtn.setEnabled(true); } else { delBtn.setEnabled(false); } } @Override public void onClick(View v) { switch (v.getId()) { // 删除按钮 case R.id.del_btn: new AlertDialog.Builder(this) .setTitle(R.string.clearConfirmation_title) .setMessage(R.string.clearConfirmation) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @SuppressWarnings("unchecked") @Override public void onClick(DialogInterface dialog, int which) { final ProgressDialog progressDialog = ProgressDialog.show(MultiSelectDeleteActivity.this, getString(R.string.clearProgress_title), "", true, false); final AsyncTask<HashSet<String>, Integer, Cursor> deleteWork = new AsyncTask<HashSet<String>, Integer, Cursor>() { Uri uri = null; @Override protected Cursor doInBackground(HashSet<String> ... params) { // 后台工作线程执行删除联系人记录操作 HashSet<String> ids = params[0]; for (String id : ids) { Log.i(TAG, "deleted id= " + id); uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.valueOf(id)); MultiSelectDeleteActivity.this.getContentResolver().delete(uri, null, null); } Log.i(TAG, "doInBackground statusMap size=" + statusMap.size()); // 清除所有被选中的联系人Id delListAdapter.idSet.clear(); cursor = MultiSelectDeleteActivity.this.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION, null, null, null); return cursor; } // 删除操作的实时进度,本案例不对此做任何处理 @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } // 删除操作执行完毕后回调此方法,可以得到处理结果,并通知UI更新 @Override protected void onPostExecute(Cursor result) { super.onPostExecute(result); Log.i(TAG, "result getCount= " + result.getCount()); if(result.getCount() == 0){ // 删除全部记录后,全选CheckBox应该被禁用(不能再点击),当有新记录加入时才可以重新启用它 selAllChk.setChecked(false); selAllChk.setEnabled(false); } delBtn.setEnabled(false); statusMap.clear(); // 删除操作完成后,重置剩下的记录为未选中状态 for (int i = 0; i < result.getCount(); i++) { statusMap.put(i, false); } delListAdapter.cursor = result; delListAdapter.notifyDataSetChanged(); progressDialog.dismiss(); } }; progressDialog.show(); deleteWork.execute(delListAdapter.idSet); } }) .setCancelable(true) .create() .show(); break; // 取消按钮 case R.id.can_btn: break; } }}
3案例效果展示
4案例代码下载
点我下载源码
- Android应用开发之多选删除之二
- Android应用开发之多选删除之一
- Android开发之多线程下载(二)
- Android知识点之多媒体应用开发
- Android开发之Animation应用(二)
- Android开发之AppWidget应用(二)
- Android开发之PopupWindow应用(二)
- Android开发之AppWidget应用(二)
- Android开发之倒计时应用(二)
- Android源码开发之添加/删除系统应用
- Android开发之应用与开发环境(二)
- android应用开发之多次触发toast的处理
- Android应用开发之XML文件解析之二
- Android开发之多点触控
- Android开发之多点触控
- Android开发之多线程
- Android之多线程解析(二)之Runnable、Callable、FutureTask
- android应用开发之intent的妙用二
- 新网站:http://www.searchufo.org开张
- UVA 10037 - Bridge
- 可穿戴设备为什么那么火
- 编码恢复
- SQL Server 日期和时间函数
- Android应用开发之多选删除之二
- 第十四周上机任务项目2
- HTTP协议的POST和GET的区别
- Android程序进行混淆,在导出签名apk包时出错!
- NYOJ 599 奋斗的小蜗牛
- android 混淆文件project.properties和proguard-project.txt
- NYOJ 7 街区最短路径
- Symmetric Tree
- git常用命令