效果如下图所示:
主要涉及三个文件,详细内容如下:
ListView的子项目,文件名:person_row.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:descendantFocusability="blocksDescendants" android:layout_width="match_parent" android:layout_height="match_parent"> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" android:clickable="false" android:id="@+id/contact_checbox" /> <TextView android:layout_width="2dp" android:layout_height="wrap_content" android:id="@+id/contact_id" android:visibility="invisible" /> <TextView android:layout_width="60dp" android:layout_height="wrap_content" android:text="" android:id="@+id/contact_name" android:textAlignment="textStart" android:background="#ffe222" style="@style/style_edit" /> <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:text="" android:id="@+id/contact_mobile" android:textAlignment="textStart" android:background="#34ff1d" style="@style/style_edit" /> <TextView android:layout_width="60dp" android:layout_height="wrap_content" android:text="" android:id="@+id/contact_title" android:background="#cafeff" /> <TextView android:layout_width="60dp" android:layout_height="wrap_content" android:text="" android:id="@+id/contact_remark1" android:background="#b5aaff" style="@style/style_edit" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:id="@+id/contact_remark2" /> </LinearLayout>
布局文件,文件名contact_activity:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.wallimn.iteye.msgutil.ContactActivity"> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/contact_list" android:layout_alignParentStart="true" /> </RelativeLayout>
JAVA文件,文件名ContactActivity :
package com.wallimn.iteye.msgutil; import android.app.ProgressDialog; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CheckedTextView; import android.widget.CompoundButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; public class ContactActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { /** * 简短的联系人信息类 */ public static class ContactDetail{ public String id; public String name; public String mobile; public String title; public String remark1; public boolean checked; public ContactDetail(String id,String name,String mobile){ this.id = id; this.name = name; this.mobile = mobile; this.title = ""; this.remark1=""; } public ContactDetail(String id,String name,String mobile,String title,String remark1){ this.id = id; this.name = name; this.mobile = mobile; this.title = title; this.remark1 = remark1; } } /** * 所有联系人列表,读取手机通讯录的结果 */ List<ContactDetail> allContacts; /** * 界面元素 */ ListView listView; /** * 读取联系人的线程 */ Thread readContactsThread; Handler messageHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case UPDATE_LIST: if (proDialog != null) { proDialog.dismiss(); proDialog = null; } freshListView(); } } }; private final int UPDATE_LIST=0x3390; private ProgressDialog proDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contact); listView = (ListView)this.findViewById(R.id.contact_list); listView.setItemsCanFocus(false); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setOnItemClickListener(this); allContacts = new LinkedList<ContactDetail>(); readContactsThread=new Thread(new ReadContactsRunnable()); readContactsThread.start(); proDialog = ProgressDialog.show(ContactActivity.this, "请稍候","正在读取联系人......", true, true); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_contact, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); //点击菜单上的确定后,将数据保存到本机的数据库中。 if (id == R.id.menu_ok) { Map<String ,String> sels = new HashMap<String ,String>(); SQLiteDatabase db = DbUtil.getConnection(this); Map<String,String> ids = DbUtil.getLocalContactId(db); String insertsql = "insert into t_person (name,mobile,contactid) values(?,?,?)"; String deletesql = "delete from t_person where contactid=?"; int selCount = 0; for(ContactDetail cd:this.allContacts) { //如果选中、且本地数据库中没有,插入本地数据库 if (cd.checked == true) { if (!ids.containsKey(cd.id)) { db.execSQL(insertsql, new String[]{cd.name, cd.mobile, cd.id}); Log.i("wallimn", "插入:" + cd.name); selCount++; } sels.put(cd.id, "1"); } } Log.i("wallimn", "共计:" + allContacts.size() + ",选中:" + selCount); //删除这次未选的。 for(String key:ids.keySet()){ if(!sels.containsKey(key)){ db.execSQL(deletesql,new Object[]{key}); } } db.close();; db=null; this.finish(); return true; } else if(id == R.id.menu_cancel) { this.finish(); return true; } return super.onOptionsItemSelected(item); } /** * 刷新ListView显示 */ private void freshListView(){ Log.i("wallimn","联系人装载完毕,准备生成列表,读取联系人数量:"+allContacts.size()); if(allContacts!=null){ ContactAdapter adapter = new ContactAdapter(ContactActivity.this,this.allContacts); //读取数据库中保存的常用联系人,如果存在,设置该行为选中状态。 Map<String,String> ids = DbUtil.getLocalContactId(ContactActivity.this); for(ContactDetail cd :allContacts){ if(ids.containsKey(cd.id))cd.checked=true; } listView.setAdapter(adapter); } Log.i("wallimn","列表生成完毕"); } /** * 设置了ListView中的checkbox不能获取焦点、不能点击,ListView才会响应这个事件 * @param parent * @param view * @param position * @param id */ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Log.i("wallimn","ItemClick被点击,position="+position+" , id="+id); CheckBox cb = (CheckBox)view.findViewById(R.id.contact_checbox); cb.setChecked(!cb.isChecked()); allContacts.get((int) id).checked = cb.isChecked(); } /** * 读取联系人的线程,读取完成后,数据保存到List中,最后发送消息,通知界面更新显示 */ class ReadContactsRunnable implements Runnable{ @Override public void run() { Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.PHOTO_ID }; String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'"; String[] selectionArgs = null; String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; ContentResolver contentResolver = ContactActivity.this.getContentResolver(); Cursor cursor=contentResolver.query(uri, projection, selection, selectionArgs, sortOrder); //Cursor cursor=managedQuery(uri, projection, selection, selectionArgs, sortOrder); Cursor phonecur = null; int count = 0; while (cursor.moveToNext()){ // 取得联系人名字 int nameFieldColumnIndex = cursor.getColumnIndex(android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME); String name = cursor.getString(nameFieldColumnIndex); // 取得联系人ID String contactId = cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID)); //phonecur = managedQuery(android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); phonecur = contentResolver.query(android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); // 取得电话号码(可能存在多个号码) while (phonecur.moveToNext()){ String strPhoneNumber = phonecur.getString(phonecur.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER)); strPhoneNumber = strPhoneNumber.replace("-", "").replace("+86","").replace(" ",""); if(strPhoneNumber.length()==11) { //allContacts.add(new ContactDetail(contactId, "wallimn", "13801380000")); allContacts.add(new ContactDetail(contactId, name, strPhoneNumber)); } } count++; phonecur.close(); phonecur = null; //if(count>20)break; } cursor.close(); Message loaded=new Message(); loaded.what=UPDATE_LIST; messageHandler.sendMessage(loaded); } } @Override protected void onDestroy() { super.onDestroy(); allContacts.clear(); } /** * 联系人信息适配器 */ public static class ContactAdapter extends BaseAdapter{ private List<ContactDetail> list; private Context context; public List<ContactDetail> getList(){ return this.list; } /** * 构造函数,传入list参数,避免代码耦合 * @param list */ public ContactAdapter(Context context,List<ContactDetail> list){ this.list = list; this.context = context; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ContactDetail cd = list.get(position); final int index = position; if(convertView == null){ convertView = LayoutInflater.from(context).inflate(R.layout.person_row, null); }else{ ; } ((TextView)convertView.findViewById(R.id.contact_id)).setText(cd.id); ((TextView)convertView.findViewById(R.id.contact_name)).setText(cd.name); ((TextView)convertView.findViewById(R.id.contact_mobile)).setText(cd.mobile); ((TextView)convertView.findViewById(R.id.contact_title)).setText(cd.title); ((TextView)convertView.findViewById(R.id.contact_remark1)).setText(cd.remark1); ((CheckBox) convertView.findViewById(R.id.contact_checbox)).setChecked(cd.checked); return convertView; } } }