Android带索引联系人列表

千金一刻莫空度,老大无成空自伤。这篇文章主要讲述Android带索引联系人列表相关的知识,希望能为你提供帮助。
网上android联系人列表的样例也非常多,都和微信的联系人差点儿相同,因为项目用到了联系人列表索引功能(产品把字母item给去掉了),只是也还是好实现。这里我也来分享分享我的实现,免得以后忘了。那先看看效果(Demo在结尾有下载地址):

Android带索引联系人列表

文章图片


要达到的效果就是这么简单。
先说说思路吧:首先为联系人对象加入一个pinyin字段,当获取到了联系人原始数据后,把每一个联系人的名字转换为拼音。并为pinyin字段设置值。
然后获取联系人中出现过哪些字母的拼音保存为数组(这就是字母的item),然后和联系人拼音再组合成新的数组,利用Arrays.sort排序功能,就依次按字母顺序拍好了联系人列表,接下来就是把字母在联系人列表中出现的位置给保存起来,绘制右边字母索引时,给对应的字母设置当前字母在联系人列表的位置,滑动到某一个字母是,就把listview移动到那个位置即可了。


一:先看看提取联系人中出现的字母,并排序

/** * 把数据排序。并把A-Z顺序加进去 * * @param carTypes * @return */ public String[] sortIndex(List< ConstastBean> constastBeans) { TreeSet< String> set = new TreeSet< String> (); for (ConstastBean constastBean : constastBeans) { char ch = constastBean.getPinyin().charAt(0); set.add(String.valueOf(ch).toUpperCase(Locale.getDefault())); // 获取出现的首字母 } String[] names = new String[constastBeans.size() + set.size()]; // 新数组,用于保存首字母 + 联系人拼音 int i = 0; for (String string : set) { // 把set中的字母加入到新数组中(前面) names[i] = string; i++; } < span style="white-space:pre"> < /span> //把联系人拼音提取到一个数组中 String[] pyheader = new String[constastBeans.size()]; for (int j = 0; j < constastBeans.size(); j++) { pyheader[j] = constastBeans.get(j).getPinyin(); }System.arraycopy(pyheader, 0, names, set.size(), pyheader.length); // < span style="font-family: Arial, Helvetica, sans-serif; "> 把联系人拼音加入到后面,结果就是联系人拼音和出现过的首字母在一个数组里面(是无序的)< /span> // 自己主动依照首字母排序 Arrays.sort(names, String.CASE_INSENSITIVE_ORDER); // 严格依照字母顺序排序,忽略字母大写和小写,结果为按拼音排序的数组返回 return names; }

这个返回的就是排好序的字母顺序了(如[A, 安妮,G,盖伦...Z])。

二:接下来就是依据返回的顺序,把联系人对象排序

/** * 依据名字排序对数据进行排序 由于默认是数字在首位,为了把数字排到末尾,须要进行转换 * * @param arry * @return */ public ArrayList< ConstastBean> getAllLists(String[] arry) { ArrayList< ConstastBean> lists = new ArrayList< ConstastBean> (); // 保存排好序的数据 ArrayList< ConstastBean> lists2 = new ArrayList< ConstastBean> (); // 保存数字开头的数据 ArrayList< ConstastBean> lists3 = new ArrayList< ConstastBean> (); // 保存字母数据 // 对数据进行排序 for(int i = 0; i < arry.length; i++) { for(int j = 0; j < sourceData.size(); j++) { if(arry[i].equals(sourceData.get(j).getPinyin())) { lists.add(sourceData.get(j)); break; } // else //须要显示单个字母的item,这里就不用凝视。在adapter中应给为这个item单独设置一个布局 //{ //ConstastBean contactBean = new ConstastBean(); //contactBean.setPinyin(arry[i]); //contactBean.setNickName(arry[i]); //lists.add(contactBean); //break; //} } } // 分离出数字数据和字母数据 int index = getLetter(lists); // 获取字母开头的位置 for(int i = 0; i < lists.size(); i++) { if(i < index) { lists2.add(lists.get(i)); } else { lists3.add(lists.get(i)); } } lists.clear(); lists.addAll(lists3); lists.addAll(lists2); return lists; }


因为排好序的是数字在字母前面,可是这里须要数字在后面,所以先查询第一个字母出现的位置。然后从那个位置截取为2个集合。再把数字集合加入到字母集合后面即可了。
三:初始化工作都做好了。就该遍历获取每一个字母所相应的位置了

< span style="white-space:pre"> < /span> selector = new HashMap< String, Integer> (); // 遍历排好序的数据,获取每一个字母的位置 for (int i = 0; i < indexStr.length; i++) { for (int j = 0; j < datas.size(); j++) { if (datas.get(j).getPinyin().toLowerCase(Locale.getDefault()).startsWith(indexStr[i< span style="white-space:pre"> < /span> ].toLowerCase(Locale.getDefault()))) { selector.put(indexStr[i], j); break; } String pinyin = datas.get(j).getPinyin(); if(indexStr[i].equals("#") & & isNumeric(pinyin.substring(0,1))) { selector.put(indexStr[i], j); return; } } }


返回的结果就类似于这样的:{D=2, #=23, E=4, G=5, A=0, L=11, M=12, N=14, H=6, J=8, K=10, T=19, V=20, S=16, R=15, Z=21}
/** * 绘制索引条 */ public void drawIndexView() { LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, height); for (int i = 0; i < indexStr.length; i++) { TextView tv = new TextView(this); tv.setLayoutParams(params); tv.setText(indexStr[i]); tv.setGravity(Gravity.CENTER); tv.setTextColor(this.getResources().getColor(R.color.indexs_color)); tv.setTextSize(13); layoutIndex.addView(tv); layoutIndex.setOnTouchListener(new OnTouchListener() {@Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub float y = event.getY(); int index = (int) y / height; // 得到点击字母位置的索引 String key = ""; if (index < indexStr.length & & index > -1) { key = indexStr[index]; if (selector.containsKey(key)) { int position = selector.get(key); if (listView.getHeaderViewsCount() > 0) {// 加入的header给去掉 listView.setSelectionFromTop( position + listView.getHeaderViewsCount(), 0); } else { listView.setSelectionFromTop(position, 0); // 滑动到第一项 } } if (key.equals("↑")) { listView.setSelectionFromTop(0, 0); // 滑动到第一项 } } if(!key.equals("")) { showTv.setText(key); showTv.setVisibility(View.VISIBLE); }switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_OUTSIDE: showTv.setVisibility(View.GONE); break; case MotionEvent.ACTION_DOWN: // layoutIndex.setBackground(); break; }return true; } }); } }

这样就完毕了带索引的联系人列表的实现:Demo源代码下载








【Android带索引联系人列表】












    推荐阅读