想知道效果自己先看下手机或者模拟器的联系人,字母分类栏的推动效果。
C栏目把B推上去.
package com.lee.contact; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Hashtable; import java.util.Random; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Photo; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; import android.view.View; import android.view.Window; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ListView; import android.widget.TextView; /** * 申明一下,目前没有对联系人中文进行拼音转换 只能用于英文联系人,所以中文就别测试了,肯定出问题的。 转拼音网上有资源,自己下载,我的C库是公司的就不开源了 * * @author leehom * */ public class MContactActivity extends Activity implements OnScrollListener { private ListView listView; // private EditText input; private String key; private Collator cmp = Collator.getInstance(java.util.Locale.CHINA); private ArrayList<ContactItem> srcAll = new ArrayList<ContactItem>(); // private Vibrator vibrator; private MoveLayout board; private TextView name; private MoveLayout move_board; private TextView move_name; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); // deleteAll();// 最好在模拟器上测试,不然联系人全部删除光了 // generater(1000);// 添加1000联系人 // vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); setContentView(R.layout.friend_list); listView = (ListView) findViewById(R.id.list); board = (MoveLayout) findViewById(R.id.board); board.setBackgroundColor(0xFF333333); name = (TextView) board.findViewById(R.id.name); move_board = (MoveLayout) findViewById(R.id.move_board); move_board.setBackgroundColor(0xFF333333); move_name = (TextView) move_board.findViewById(R.id.move_name); listView.setOnScrollListener(this); // listView.setOnItemLongClickListener(new OnItemLongClickListener() { // // @Override // public boolean onItemLongClick(AdapterView<?> arg0, View arg1, // int position, long arg3) { // // TODO Auto-generated method stub // vibrator.vibrate(50); // return false; // } // }); // input = (EditText) findViewById(R.id.input); // input.addTextChangedListener(new TextWatcher() { // // @Override // public void onTextChanged(CharSequence s, int start, int before, // int count) { // // TODO Auto-generated method stub // // } // // @Override // public void beforeTextChanged(CharSequence s, int start, int count, // int after) { // // TODO Auto-generated method stub // // } // // @Override // public void afterTextChanged(Editable s) { // // TODO Auto-generated method stub // key = s.toString(); // // handler.sendEmptyMessage(0); // } // }); // input.requestFocus(); // long begin = System.currentTimeMillis(); getContacts(); // long use = System.currentTimeMillis() - begin; } // public Handler handler = new Handler() { // // @Override // public void handleMessage(Message msg) { // // TODO Auto-generated method stub // check(); // } // // }; public void check() { ArrayList<ContactItem> list = new ArrayList<ContactItem>(); for (int i = 0; i < srcAll.size(); i++) { ContactItem info = (ContactItem) srcAll.get(i).clone(); int ch; if ((ch = info.name.toLowerCase().indexOf(key.toLowerCase())) != -1) { StringBuffer html = new StringBuffer(); html.append(info.name.substring(0, ch)); html.append("<font color=#00FF00>"); html.append(info.name.substring(ch, ch + key.length())); html.append("</font>"); html.append(info.name.substring(ch + key.length(), info.name.length())); info.html = html.toString(); list.add(info); } } adapter.setList(list); listView.setAdapter(adapter); } // 查询联系人 private void getContacts() { Hashtable<String, ContactItem> map = new Hashtable<String, ContactItem>(); Cursor cursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); int index = 0; // 循环遍历 if (cursor.moveToFirst()) { do { ContactItem info = new ContactItem(); // 获得联系人的ID号 info.contactId = cursor.getString(cursor .getColumnIndex(BaseColumns._ID)); // 获得联系人姓名 info.name = cursor .getString(cursor .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); // 获得联系人号码数 info.phoneCount = cursor .getInt(cursor .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); if (info.phoneCount > 0) { if (++index % 5 == 0) info.changeToVideo(); else if (index % 9 == 0) info.changeToMsg(index); else if (index % 13 == 0) info.changeToTalk(); map.put(info.contactId, info); } } while (cursor.moveToNext()); } Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); // 循环遍历 if (phones.moveToFirst()) { do { String id = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); String num = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); if (map.containsKey(id)) { ContactItem info = map.get(id); info.num = num; } } while (phones.moveToNext()); } Cursor email = getContentResolver().query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, null, null, null); if (email.moveToFirst()) { do { String id = email .getString(email .getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); String eml = email .getString(email .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); if (map.containsKey(id)) { ContactItem info = map.get(id); info.email = eml; } } while (email.moveToNext()); } Enumeration<String> keys = map.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); srcAll.add(map.get(key)); } Collections.sort(srcAll, new Comparator<ContactItem>() { @Override public int compare(ContactItem r1, ContactItem r2) { return cmp.compare(r1.name, r2.name); } }); adapter = new ContactAdapter(this, srcAll); listView.setAdapter(adapter); } private ContactAdapter adapter; private static final String[] PHONES_PROJECTION = new String[] { Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID }; /** 联系人显示名称 **/ public static final int PHONES_DISPLAY_NAME_INDEX = 0; /** 电话号码 **/ public static final int PHONES_NUMBER_INDEX = 1; /** 得到手机SIM卡联系人人信息 **/ public void getSIMContacts() { ContentResolver resolver = getContentResolver(); // 获取Sims卡联系人 Uri uri = Uri.parse("content://icc/adn"); Cursor phoneCursor = resolver.query(uri, PHONES_PROJECTION, null, null, null); if (phoneCursor != null) { while (phoneCursor.moveToNext()) { // 得到手机号码 String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX); // 当手机号码为空的或者为空字段 跳过当前循环 if (TextUtils.isEmpty(phoneNumber)) continue; // // 得到联系人名称 // String contactName = phoneCursor // .getString(PHONES_DISPLAY_NAME_INDEX); // Sim卡中没有联系人头像 } phoneCursor.close(); } } public void generater(int num) { Random random = new Random(); ArrayList<String> list = new ArrayList<String>(); InputStream is = getResources().openRawResource(R.raw.name); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(is, "GBK")); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { String line = null; while ((line = reader.readLine()) != null) { int ch = line.indexOf(","); if (ch != -1) list.add(line.substring(0, ch)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } int min = num < list.size() ? num : list.size(); for (int i = 0; i < list.size() && i < num; i++) { // String name = str.substring(rand, rand + random.nextInt(2) + 2); String name = list.get(i); String phone = "186" + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)) + String.valueOf(random.nextInt(10)); System.out.println("left:" + min--); insertContact(name, phone); } } public void insertContact(String name, String phone) { ContentValues values = new ContentValues(); // insert a null value Uri rawContactUri = getContentResolver().insert( RawContacts.CONTENT_URI, values); long rawContactsId = ContentUris.parseId(rawContactUri); // 往刚才的空记录中插入姓名 values.clear(); values.put(StructuredName.RAW_CONTACT_ID, rawContactsId); values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); values.put(StructuredName.DISPLAY_NAME, name); getContentResolver().insert(Data.CONTENT_URI, values); // 插入电话 values.clear(); values.put(Phone.RAW_CONTACT_ID, rawContactsId); values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); values.put(Phone.NUMBER, phone); getContentResolver().insert(Data.CONTENT_URI, values); } public void deleteAll() { getContentResolver().delete(ContactsContract.Data.CONTENT_URI, null, null); getContentResolver().delete(ContactsContract.RawContacts.CONTENT_URI, null, null); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub View mView = view.getChildAt(1); if (adapter != null && visibleItemCount + 1 < adapter.getCount()) { ContactItem item = adapter.getItem(firstVisibleItem + 1); if (adapter.getItem(firstVisibleItem).isTotalHead) { move_board.setVisibility(View.GONE); board.setVisibility(View.GONE); } else if (item.isHead) { move_board.setVisibility(View.VISIBLE); int vY = mView.getTop(); if (board.getInit_height() >= vY) { // 重叠 board.setVisibility(View.GONE); move_board.move(vY - board.getInit_height()); char c = adapter.getItem(firstVisibleItem).name.charAt(0); String s = String.valueOf(c); move_name.setText(s); } else { // 没有重叠显示,重置为0 move_board.move(0); } } else { char c = item.name.charAt(0); String s = String.valueOf(c); name.setText(s); // 不是分组显示 board.setVisibility(View.VISIBLE); } } } }
package com.lee.contact; import android.content.Context; import android.os.AsyncTask; import android.util.AttributeSet; import android.widget.LinearLayout; import android.widget.RelativeLayout; public class MoveLayout extends LinearLayout { private int init_height; public MoveLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub super.onLayout(changed, l, t, r, b); init_height = b - t; } public int getInit_height() { return init_height; } public void move(int value) { new AsynMove().execute(new Integer[] { value }); } private class AsynMove extends AsyncTask<Integer, Integer, Void> { @Override protected Void doInBackground(Integer... params) { // TODO Auto-generated method stub publishProgress(params); return null; } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams(); lp.topMargin = values[0]; setLayoutParams(lp); } } }
package com.lee.contact; import java.io.Serializable; public class ContactItem implements Serializable, Cloneable { private static final long serialVersionUID = 1L; private static final String serverIP = "@audivi.com"; public static final byte MESSAGE = 1; public static final byte VIDEO = 2; public static final byte TALK = 3; public static final byte OFF_LINE = 4; public static final byte ON_LINE = 5; protected String contactId; protected String name; protected String html; protected String email; protected String num; protected int phoneCount; protected int msgCount; protected byte status; protected boolean isHead; protected boolean isTotalHead; @Override protected Object clone() { // TODO Auto-generated method stub try { return super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 更新用户消息条目 * @param msgCount * 消息条目 */ public void changeToMsg(int msgCount) { status = MESSAGE; this.msgCount = msgCount; } /** * 切换到视频状态 */ public void changeToVideo() { status = VIDEO; } /** * 切换到语音状态 */ public void changeToTalk() { status = TALK; } public String getSipUri() { if (num != null) return num.replace("@", ".") + serverIP; else return email.replace("@", ".") + serverIP; } }
package com.lee.contact; import java.util.ArrayList; import android.content.Context; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class ContactAdapter extends BaseAdapter { protected ArrayList<ContactItem> list; protected Context context; protected LayoutInflater inflater; public ContactAdapter(Context context, ArrayList<ContactItem> list) { // TODO Auto-generated constructor stub ArrayList<ContactItem> newList = new ArrayList<ContactItem>(); for (int i = 0; i < list.size(); i++) { ContactItem item = list.get(i); char fc = item.name.charAt(0); if (i + 1 < list.size()) { char temp = list.get(i + 1).name.charAt(0); if (i == 0) { ContactItem ci = new ContactItem(); ci.name = "显示" + list.size() + "位联系人"; ci.isHead = true; ci.isTotalHead = true; newList.add(ci); ci = new ContactItem(); ci.name = String.valueOf('A'); ci.isHead = true; newList.add(ci); newList.add(item); } else if (fc != temp) { ContactItem ci = new ContactItem(); ci.name = String.valueOf((char) (fc + 1)); ci.isHead = true; newList.add(item); newList.add(ci); } else { newList.add(item); } } } this.list = newList; this.context = context; inflater = LayoutInflater.from(context); } public void setList(ArrayList<ContactItem> list) { this.list = list; } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public ContactItem getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub View view = null; if (convertView != null) { view = convertView; } else { LinearLayout layout = (LinearLayout) inflater.inflate( R.layout.chat_contact_item, parent, false); view = layout; } TextView name = (TextView) view.findViewById(R.id.name); // ImageView status = (ImageView) view.findViewById(R.id.status); ContactItem info = getItem(position); if (info.email != null) name.setText(Html.fromHtml((info.html == null ? info.name : info.html) + "(" + info.email + ")")); else name.setText(Html.fromHtml((info.html == null ? info.name : info.html))); ImageView head = (ImageView) view.findViewById(R.id.head); if (info.isHead) { view.setBackgroundColor(0xFF333333); head.setVisibility(View.GONE); } else { view.setBackgroundColor(0x0); head.setVisibility(View.VISIBLE); } // switch (info.status) { // case ContactItem.MESSAGE: // status.setBackgroundResource(R.drawable.chat_contact_message); // break; // case ContactItem.VIDEO: // status.setBackgroundResource(R.drawable.chat_contact_video); // break; // case ContactItem.TALK: // status.setBackgroundResource(R.drawable.chat_contact_stop); // break; // default: // status.setBackgroundDrawable(null); // break; // } // TextView msgCount = (TextView) view.findViewById(R.id.msgcount); // msgCount.setVisibility(View.GONE); // if (info.msgCount > 0) { // msgCount.setText(String.valueOf(info.msgCount)); // msgCount.setVisibility(View.VISIBLE); // } return view; } }
工程项目下载: http://download.csdn.net/detail/lh15871815717/3896391