3.CursorAdapter

会话页面

点击菜单时编辑的按钮显示,其余的时候gone

ConversationUI

public class ConversationUI extends Activity implements OnItemClickListener, OnClickListener{
 private ListView listView;
 private Button btnNewMessage;
 private Button btnSelectAll;
 private Button btnSelectNull;
 private Button btnDeleteMsg;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_conversation);
 this.ctx = this;
		init();
		flushState();
		prepareData();
 }
 /**
	 * 要查询的列
	 */
 private String[] projection={
 "sms.body AS snippet",
 "sms.thread_id AS _id",//需要主键可是没有,可以起个别名
 "groups.msg_count AS msg_count",
 "address as address",
 "date as date"
 };
 /**
	 * 短信内容所在列的索引值 为 0
	 */
 private final int INDEX_BODY = 0;
 /**
	 * 会话ID所在列的索引值 为 1
	 */
 private final int INDEX_THREAD_ID = 1;
 /**
	 * 短信数量所在列的索引值 为 2
	 */
 private final int INDEX_MSG_COUNT = 2;
 /**
	 * 短信联系人电话所在列的索引值 为 3
	 */
 private final int INDEX_ADDRESS = 3;
 /**
	 * 短信日期所在列的索引值 为 4
	 */
 private final int INDEX_DATE = 4;
 /**
	 * 给listView 准备数据
	 */
 private void prepareData() {
 /*
		 * 查询数据库,如果数据太多了,会造成ANR异常,所 以,一般都会开子线程,查询数据,然后,用handler将结果,回传
		 */
  MyQueryHandler queryHandler = new MyQueryHandler(getContentResolver());
		queryHandler.startQuery(234, adapter, MyConstants.URI_CONVERSATION, projection, null, null, " date desc");//按日期倒序查询
 }
 private void init() {
		btnNewMessage = (Button) findViewById(R.id.btn_new_message_conversation);
		btnSelectAll = (Button) findViewById(R.id.btn_select_all_conversation);
		btnSelectNull = (Button) findViewById(R.id.btn_select_null_conversation);
		btnDeleteMsg = (Button) findViewById(R.id.btn_delete_message_conversation);
		btnNewMessage.setOnClickListener(this);
		btnSelectAll.setOnClickListener(this);
		btnSelectNull.setOnClickListener(this);
		btnDeleteMsg.setOnClickListener(this);
		listView = (ListView) findViewById(R.id.lv_conversation);
		adapter = new MyListAdapter(this, null);//可以先传个null
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(this);
		selectItemSet = new HashSet<Integer>();//删除时选中的集合
 }
 private boolean isEditState = false;
 private void flushState() {
 if(isEditState){//编辑状态
			btnNewMessage.setVisibility(View.GONE);
			btnSelectAll.setVisibility(View.VISIBLE);
			btnSelectNull.setVisibility(View.VISIBLE);
			btnDeleteMsg.setVisibility(View.VISIBLE);
 }else{//非编辑状态
			btnNewMessage.setVisibility(View.VISIBLE);
			btnSelectAll.setVisibility(View.GONE);
			btnSelectNull.setVisibility(View.GONE);
			btnDeleteMsg.setVisibility(View.GONE);
 }
 //判断listview 的条目是否有被选中,如果没有被选中的,btnSelectNull 和  btnDeleteMsg 应该处于不可用的状态 否则,是可用的状态
 if(selectItemSet.size()==0){// listview条目没有被选择
			btnSelectNull.setEnabled(false);
			btnDeleteMsg.setEnabled(false);
 }else{
			btnSelectNull.setEnabled(true);
			btnDeleteMsg.setEnabled(true);
 }
 // 根据 selectItemSet 集合当中的内容数量,改变 全选按钮的状态
 // 判断  selectItemSet 的size 和listView的条目数量,是否相同,如果相同,全选按钮,就不可用。
 if(selectItemSet.size() == adapter.getCount()){
			btnSelectAll.setEnabled(false);
 }else{
 // 否则,是可用的
			btnSelectAll.setEnabled(true);
 }
 }
 private MyListAdapter adapter ;
 public Context ctx;
 class MyListAdapter extends CursorAdapter{
 public MyListAdapter(Context context, Cursor c) {
 super(context, c);
 }
 @Override
 /**
		 * 当 conterView是null时,需要用户创建view 的时候调 
		 */
 public View newView(Context context, Cursor cursor, ViewGroup parent) {
 View view = View.inflate(ctx, R.layout.list_item_conversation,null);
 ViewHolder vh = new ViewHolder();
			vh.checkbox = (ImageView) view.findViewById(R.id.iv_checkbox_list_item);
			vh.face = (ImageView) view.findViewById(R.id.iv_face_list_item);
			vh.address = (TextView) view.findViewById(R.id.tv_address_list_item);
			vh.body = (TextView) view.findViewById(R.id.tv_body_list_item);
			vh.date = (TextView) view.findViewById(R.id.tv_date_list_item);
			view.setTag(vh);
 return view;
 }
 @Override
 /**
		 * 为itemview设置内容时调用
		 * view 即 newView 方法的返回值
		 */
 public void bindView(View view, Context context, Cursor cursor) {
 ViewHolder vh = (ViewHolder) view.getTag();
 //显示短信内容
			vh.body.setText(cursor.getString(INDEX_BODY));
 //显示日期:
 long when = cursor.getLong(INDEX_DATE);
 String dateStr;
 //使用系统工具类,判断是否是今天
 if(DateUtils.isToday(when)){
				dateStr = DateFormat.getTimeFormat(ctx).format(when);
 }else{
				dateStr = DateFormat.getDateFormat(ctx).format(when);
 }
			vh.date.setText(dateStr);
 //显示联系人地址:
 String number = cursor.getString(INDEX_ADDRESS);
 int msgcount = cursor.getInt(INDEX_MSG_COUNT);// 获得短信的数量
 String name = Tools.findNameByNumber(ctx, number);
 if(name == null){//表明无此联系人
				vh.address.setText(number+"("+msgcount+")");
 }else{
				vh.address.setText(name+"("+msgcount+")");
 }
 //显示联系人的头像:
 // 根据电话号码,查询联系人ID
 int contactId = Tools.findIDByNumber(ctx, number);
 // 如果 ID = -1 表明,无此联系人,此时,应设置一个 未知的联系人头像
 if(contactId == -1){
				vh.face.setBackgroundResource(R.drawable.ic_unknow_contact_picture);
 }else{
 // 根据ID 获得联系人头像,
 Bitmap bitmap = Tools.getFaceById(ctx, ""+contactId);
 //如果 bitmpa == null 表明,此联系人,无头像,应设置,一个联系人的默认的头像
 if(bitmap == null){
					vh.face.setBackgroundResource(R.drawable.ic_contact_picture);
 }else{
 //否则,将bitmap 设置为联系人的头像
					vh.face.setBackgroundDrawable(new BitmapDrawable(bitmap));
 }
 }
 /*
			 * 设置 checkBox
			 */
 //如果是编辑状态,显示checkBox,
 if(isEditState){
				vh.checkbox.setVisibility(View.VISIBLE);
 // 该条目对应的会话ID
 int threadId = cursor.getInt(INDEX_THREAD_ID);
 //判断集合当中,是否有该条目对应的会话ID,如果有,表示是选中状态,如果没有,是没选中状态。
 if(selectItemSet.contains(threadId)){
					vh.checkbox.setEnabled(true);
 }else{
					vh.checkbox.setEnabled(false);
 }
 }else{
 //否则,隐藏
				vh.checkbox.setVisibility(View.GONE);
 }
 }
 }
 /**
	 * 存储在编辑状态下,选中的listView的条目 
	 */
 private HashSet<Integer> selectItemSet;
 class ViewHolder{
 public ImageView checkbox;
 public ImageView face;
 public TextView address;
 public TextView body;
 public TextView date;
 }
 @Override
 /**
	 * 第一次点击menu按键时,调用,用于创建菜单选 项
	 */
 public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, ID_SEARCH, 0, "搜索");
		menu.add(0, ID_EDIT, 0, "编辑");
		menu.add(0, ID_CANCEL_EDIT, 0, "取消编辑");
 return true;
 }
 private final int ID_SEARCH=100;
 private final int ID_EDIT=101;
 private final int ID_CANCEL_EDIT=102;
 @Override
 /**
	 * 每次按menu按键的时候,调用,做一些准备工作
	 */
 public boolean onPrepareOptionsMenu(Menu menu) {
 if(isEditState){//如果是编辑状态
			menu.findItem(ID_EDIT).setVisible(false);
			menu.findItem(ID_SEARCH).setVisible(false);
			menu.findItem(ID_CANCEL_EDIT).setVisible(true);
 }else{
			menu.findItem(ID_EDIT).setVisible(true);
			menu.findItem(ID_SEARCH).setVisible(true);
			menu.findItem(ID_CANCEL_EDIT).setVisible(false);
 }
 return true;
 }
 @Override
 /**
	 * 当选择某一个菜单时,调用
	 */
 public boolean onOptionsItemSelected(MenuItem item) {
 switch (item.getItemId()) {
 case ID_SEARCH:
 break;
 case ID_EDIT: // 编辑菜单
			isEditState = true;
			flushState();
 break;
 case ID_CANCEL_EDIT: //取消编辑
			isEditState = false;
 //清空集合
			selectItemSet.clear();
			flushState();
 break;
 }
 return true;
 }
 @Override
 /**
	 * 响应listview的条目点击事件
	 */
 public void onItemClick(AdapterView<?> parent, View view, int position,
 long id) {
 //通过adapter 获得cursor
 Cursor cursor = adapter.getCursor();
 //将cursor移动到对应的位置
		cursor.moveToPosition(position);
 //取得该位置对应的会话ID
 int threadId = cursor.getInt(INDEX_THREAD_ID);
 if (isEditState) {
 // 判断 集合中是否有该会话ID,如果有,就删除,如果没有,就添加
 if (selectItemSet.contains(threadId)) {
				selectItemSet.remove(threadId);
 } else {
				selectItemSet.add(threadId);
 }
 //刷新listview
			adapter.notifyDataSetChanged();
 //刷新按钮状态
			flushState();
 }else{
 String address = cursor.getString(INDEX_ADDRESS);
 Intent intent = new Intent(this,ConversationDetail.class);
			intent.putExtra("address", address);// 将当前条目对应的联系人电话号码,传递给会话详情页面
			startActivity(intent);
 }
 }
 @Override
 /**
	 * 响应按钮的点击事件
	 * @param v
	 */
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.btn_delete_message_conversation:
 //显示确认删除的对话框 
			showConfirmDeleteDialog();
 break;
 case R.id.btn_new_message_conversation:
 // 点击新建信息按钮时,响应
 Intent intent = new Intent(this,NewMessageUI.class);
			startActivity(intent);
 break;
 case R.id.btn_select_all_conversation: // 全选按钮
 Cursor cursor = adapter.getCursor();
			cursor.moveToPosition(-1);
 while(cursor.moveToNext()){
 int threadId = cursor.getInt(INDEX_THREAD_ID);
				selectItemSet.add(threadId); // set集合的特点:无序,不可重置,如果添加的内容之前已经有了,会覆盖。
 }
 //刷新listview
			adapter.notifyDataSetChanged();
 // 刷新状态
			flushState();
 break;
 case R.id.btn_select_null_conversation: // 取消选择的按钮
 //清空集合
			selectItemSet.clear();
 //刷新listview
			adapter.notifyDataSetChanged();
 // 刷新状态
			flushState();
 break;
 }
 }
 /**
	 * 显示确认删除的对话框 
	 */
 private void showConfirmDeleteDialog() {
 AlertDialog.Builder adb = new AlertDialog.Builder(this);
		adb.setTitle("清除短信");
		adb.setMessage("确认删除这些回忆吗?");
		adb.setNegativeButton("确认", new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 // 开子线程,删除短信,
 new Thread(new DeleteMsgRunnable()).start();
 // 显示删除短信的进度对话框
				showDeleteProgressDialog();
 }
 });
		adb.setPositiveButton("取消", null);
		adb.show();
 }
 private ProgressDialog proDlg;
 /**
	 * 显示删除短信的进度对话框
	 */
 protected void showDeleteProgressDialog() {
		proDlg =new ProgressDialog(this);
		proDlg.setTitle("正在删除短信");
 //设置 进度框 为水平显示的样式,
		proDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
 // 设置进度条的最大值 = 集合的大小。
		proDlg.setMax(selectItemSet.size());
		proDlg.setButton("取消", new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
				isCancelDeleteMsg = true;
 }
 });
  // 给进度框添加,关闭时的回调 ,监听,监听的代码,会在UI线程中执行
		proDlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
 @Override
 public void onDismiss(DialogInterface dialog) {
				isEditState = false; 
				flushState();// 刷新页面状态
 System.out.println(selectItemSet);
				adapter.notifyDataSetChanged();// 刷新listview
 System.out.println("222::"+selectItemSet);
 }
 });
		proDlg.show();
 }
 /**
	 * 判断是否取消删除短信
	 */
 private boolean isCancelDeleteMsg;
 class DeleteMsgRunnable implements Runnable{
 @Override
 public void run() {
 // 遍历 selectItemSet 集合,根据会话ID,删除短信 
 for(Integer threadId : selectItemSet ){ // 用增强for循环 遍历 set集合 
 SystemClock.sleep(1000); // 会为显示效果正好,在此休眠一秒,
 if(isCancelDeleteMsg){
 break; // 跳出 for 循环
 }
 Tools.deleteMsgByThreadId(ctx,threadId);
				proDlg.incrementProgressBy(1);//让  proDlg 的水平进度条,增加刻度 
 }
 // 清空集合
			selectItemSet.clear();// 清空集合
 //关闭进度框
			proDlg.dismiss();
 // 将 isCancelDeleteMsg 复原
			isCancelDeleteMsg = false;
//			flushState();// 在子线程中不能更新UI
 }
 }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Flutter入门到实战

自定义ViewPager实现3D画廊效果

本文源码请看github地址:https://github.com/AweiLoveAndroid/My3DViewPager

4511
来自专栏Android开发指南

8.搜索

2205
来自专栏向治洪

android来电归属地提醒

现在市面上常用的一些拨号软件的一个功能,来电归属地。拨号的时候,会在拨号界面出现一个号码归属地的小框框。效果如下:而且这个小窗体还可以自定义风格,并且可以自由移...

2517
来自专栏向治洪

android自定义状态栏颜色

我们知道IOS上的应用,状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允...

3186
来自专栏酷玩时刻

Retrofit2+Rxjava+MVP 实践

此博文根据前面两篇文章 Android MVP 架构初试 Android MVP 架构封装 再结合主流框架Retrofit2+Rxjava来个实践(实现聚合网...

3274
来自专栏林冠宏的技术文章

三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。

(转载请声明出处:https://cloud.tencent.com/developer/user/1148436/activities) 前言:       ...

3409
来自专栏Samego开发资源

图片自动轮播图

3526
来自专栏Android知识点总结

5-AVI--Fragment简单封装

1013
来自专栏向治洪

viewpager循环滚动和自动轮播的问题

ViewPager是一个常用的android组件,不过通常我们使用ViewPager的时候不能实现左右无限循环滑动,在滑到边界的时候会看到一个不能翻页的动画,...

3146
来自专栏向治洪

仿淘宝收货地址,本地数据库

谁说咱们攻城狮不能写出既幽默又能懂的博客呢,本人想推出一系列博文,可以给刚接触Android开发的做一个参考,也可以与接触Android已久的各路大神比较一下,...

1.3K7

扫码关注云+社区

领取腾讯云代金券