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
}
}
}