1.checkBox的显示和隐藏
<span style="color:#330000;">/**
* 存储在编辑状态下,选中的listView的条目
*/
private HashSet<Integer> selectItemSet;
<span style="white-space:pre"> </span>/*
* 设置 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);
}</span>
</pre><pre name="code" class="java"><span style="color:#330000;">@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();
}</span>
2.点击删除按钮删除短信
<span style="color:#330000;">/**
* 显示确认删除的对话框
*/
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) {
// 1.开子线程,删除短信,
new Thread(new DeleteMsgRunnable()).start();
// 2.显示删除短信的进度对话框
showDeleteProgressDialog();
}
});
adb.setPositiveButton("取消", null);
adb.show();
}</span>
<span style="color:#330000;">
</span>
删除短信在子线程中执行
<span style="color:#330000;">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
}</span>
<span style="color:#330000;">private ProgressDialog proDlg;
/**
* 显示删除短信的进度对话框
*/
protected void showDeleteProgressDialog() {
proDlg =new ProgressDialog(this);
proDlg.setTitle("正在删除短信");
//设置 进度框 为水平显示的样式,
proDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 设置进度条的最大值 = 集合的大小。
proDlg.setMax(selectItemSet.size());
</span>
<span style="color:#330000;"><span style="white-space: pre;"> </span>//当点击取消删除时,设置isCancelDeleteMsg
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();
}</span>
3.进入会话详情页面
<span style="color:#ff0000;">
</span><span style="color:#330000;">String address = cursor.getString(INDEX_ADDRESS);
Intent intent = new Intent(this,ConversationDetail.class);
intent.putExtra("address", address);// 将当前条目对应的联系人电话号码,传递给会话详情页面
startActivity(intent);</span>
4.会话详情页面 根据电话号码设置 页面数据和布局
<span style="color:#330000;">public class ConversationDetail extends Activity implements OnClickListener{
/**
*联系人的电话号码
*/
private String address;
private Context ctx;
private ListView listView;
private EditText inputMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
address = getIntent().getStringExtra("address");
if(address == null){
throw new RuntimeException("联系人是空,我不知道显示哪个会话记录");
}
setContentView(R.layout.activity_conversation_detail);
init();
listView = (ListView) findViewById(R.id.lv_conversation_detail);
adapter = new MyListAdapter(this, null);
listView.setAdapter(adapter);
//设置listView条目之间的分隔线为null ,即,不要分隔线
listView.setDivider(null);
prepareData();
}
private void prepareData() {
MyQueryHandler myQueryHandler = new MyQueryHandler(getContentResolver());
myQueryHandler.setOnCursorChangedListener(new MyQueryHandler.IOnCursorChangedListener() {
@Override
/**
* 当adapter 获得 cursor 的时候,回调此方法
*/
public void onCursorChanged(int token, Object cookie, Cursor cursor) {
// 让listview 显示最后一行
listView.setSelection(adapter.getCount()-1);
}
});
myQueryHandler.startQuery(99, adapter, MyConstants.URI_SMS, projection, " address="+address, null, " date ");
}
/**
* 显示会话详情,所需要的列
*/
private String[] projection={
"_id","body","date","type"
};
/**
* 短信内容所在列的索引值 为 1
*/
private final int INDEX_BODY = 1;
private final int INDEX_DATE = 2;
private final int INDEX_TYPE = 3;
private void init() {
TextView title = (TextView) findViewById(R.id.tv_title_conversation_detail);
String name = Tools.findNameByNumber(ctx, address);
if(name !=null){ // 有此联系人
title.setText(name);
}else{ // 无此联系人
title.setText(address);
}
findViewById(R.id.btn_back).setOnClickListener(this);
findViewById(R.id.btn_ok).setOnClickListener(this);
inputMsg = (EditText) findViewById(R.id.et_input_msg_conversation_detail);
}
@Override
/**
* 响应按钮的点击事件
*/
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back: // 后退按钮
finish();
break;
case R.id.btn_ok: // 确定按钮
//先判断输入的是否有内容,
//如果有内容的话,就将内容以短信的形式发送出去,
String msg = inputMsg.getText().toString();
if(TextUtils.isEmpty(msg.trim())){
Toast.makeText(ctx, "请输入短信内容", 0).show();
return ;
}
// 发送短信
Tools.sendMessage(ctx,msg,address);
//清空输入框
inputMsg.setText("");
// 隐藏输入法键盘
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// 隐藏输入法的 API
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
break;
}
}
private MyListAdapter adapter;
private class MyListAdapter extends CursorAdapter{
public MyListAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
/**
* 当内容发生改变的时候,回调此方法
*/
protected void onContentChanged() {
// super 里面,做了重新查询的动作
super.onContentChanged();
// 让listView 显示最后一行
listView.setSelection(getCount()-1);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view =View.inflate(ctx, R.layout.list_item_conversation_detail, null);
ViewHolder vh = new ViewHolder();
vh.tlReceive = (TableLayout) view.findViewById(R.id.tl_receive);
vh.msgReceive = (TextView) view.findViewById(R.id.tv_msg_receive);
vh.dateReceive = (TextView) view.findViewById(R.id.tv_date_receive);
vh.tlSend = (TableLayout) view.findViewById(R.id.tl_send);
vh.msgSend = (TextView) view.findViewById(R.id.tv_msg_send);
vh.dateSend = (TextView) view.findViewById(R.id.tv_date_send);
view.setTag(vh);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder vh = (ViewHolder) view.getTag();
// 给listView条目设置内容
int type = cursor.getInt(INDEX_TYPE);// 获得短信类型
Log.d("tencent", type+"");
String text = cursor.getString(INDEX_BODY);//获得短信内容
long when = cursor.getLong(INDEX_DATE);// 获得日期
String dateStr = DateFormat.getDateFormat(ctx).format(when);
if(type == MyConstants.TYPE_RECEIVE){ // 接收到的短信
vh.tlReceive.setVisibility(View.VISIBLE);
vh.tlSend.setVisibility(View.GONE);
//设置短信内容
vh.msgReceive.setText(text);
//设置日期
vh.dateReceive.setText(dateStr);
}else{
vh.tlReceive.setVisibility(View.GONE);
vh.tlSend.setVisibility(View.VISIBLE);
//设置短信内容
vh.msgSend.setText(text);
vh.dateSend.setText(dateStr);
}
}
}
private class ViewHolder {
public TableLayout tlReceive;
public TextView msgReceive;
public TextView dateReceive;
public TableLayout tlSend;
public TextView msgSend;
public TextView dateSend;
}
</span><span style="color:#ff0000;">
</span><span style="color:#330000;">}</span><span style="color:#ff0000;">
</span>
5.发送消息 ,AutoCompleteTextView匹配数据 及选择系统联系人
<span style="color:#330000;">public class NewMessageUI extends Activity implements OnClickListener {
private AutoCompleteTextView actv;
private ImageView selectContact;
private EditText inputMsg;
private ACTVadapter adapter;
private String[] projection = { "_id", "data1", "display_name" };
private final int INDEX_NUMBER = 1;//电话号码
private final int INDEX_NAME = 2;//名字
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_message);
actv = (AutoCompleteTextView) findViewById(R.id.actv);
selectContact = (ImageView) findViewById(R.id.iv_select_contact);
inputMsg = (EditText) findViewById(R.id.et_input_msg);
selectContact.setOnClickListener(this);// 选择联系人
findViewById(R.id.btn_send_msg).setOnClickListener(this);// 发送消息
adapter = new ACTVadapter(this, null);
actv.setAdapter(adapter);
// 这个方法是cursoradapter中的---当actv 中的内容发生改变时,回调此方法
adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
// constraint 默认是当输入2个及以上的文字则返回,否则返回null
// android:completionThreshold="1"xml中配置则会变为1
// System.out.println(constraint);
Cursor cursor = getContentResolver().query(MyConstants.CONTENT_URI,
projection, "data1 like '%" + constraint + "%'", null,
null);
// Tools.printCursor(cursor);
return cursor;
}
});
}
class ACTVadapter extends CursorAdapter {
private TextView name;
private TextView number;
public ACTVadapter(Context context, Cursor c) {
super(context, c);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = View.inflate(context, R.layout.list_item_actv, null);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
name = (TextView) view.findViewById(R.id.tv_name_actv);
number = (TextView) view.findViewById(R.id.tv_number_actv);
name.setText(cursor.getString(INDEX_NUMBER));
number.setText(cursor.getString(INDEX_NAME));
}
<span style="white-space:pre"> </span>//该方法将返回的数据转换成电话号码返回给autoCompleteTextView
@Override
public CharSequence convertToString(Cursor cursor) {
String number = cursor.getString(INDEX_NUMBER);
return number;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send_msg:// 发送短信的按钮
String address = actv.getText().toString();
if (TextUtils.isEmpty(address.trim())) {
Toast.makeText(this, "请输入收件人号码", Toast.LENGTH_SHORT).show();
return;
}
String msg = inputMsg.getText().toString();
if (TextUtils.isEmpty(msg.trim())) {
Toast.makeText(this, "请输入短信内容", Toast.LENGTH_SHORT).show();
return;
}
// 开始发送短信
Tools.sendMessage(this, msg, address.trim());
// 清空输入框
inputMsg.setText("");
break;
case R.id.iv_select_contact:// 点击选择联系人的图片
Intent intent = new Intent();
intent.setAction("android.intent.action.PICK");
intent.setData(Uri.parse("content://com.android.contacts/contacts"));
startActivityForResult(intent, 99);
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// System.out.println("stringExtra::"+stringExtra);//null
if (requestCode == 99) {
String stringExtra = data.getStringExtra("phone");
System.out.println("stringExtra::" + stringExtra);
Uri uri = data.getData();
<span style="white-space:pre"> </span>//1.根据系统的uri查询_id的列(系统uri没有电话号码)
Cursor cursor = getContentResolver().query(uri,
new String[] { "_id" }, null, null, null);
// Tools.printCursor(cursor);
while(cursor.moveToNext()){
// 返回的cursor默认指向-1行 ,
int contactId = cursor.getInt(0); // 仅查询一列,所以列的索引值 输入 0
<span style="white-space:pre"> </span>//2.通过_id去查询Phone.Content.uri中的电话号码
Cursor cursor2 = getContentResolver().query(Phone.CONTENT_URI,
new String[] { "data1" }, " contact_id = " + contactId,
null, null);
while(cursor2.moveToNext()){
// 返回的cursor默认指向-1行 ,
String number = cursor2.getString(0);
actv.setText(number + "");
}
}
}
}
}</span>
</pre><pre name="code" class="java"><span style="color:#330000;">
</span>