Android带索引联系人列表

我的视频课程:《FFmpeg打造Android万能音频播放器》


        网上Android联系人列表的例子也很多,都和微信的联系人差不多,由于项目用到了联系人列表索引功能(产品把字母item给去掉了),不过也还是好实现,这里我也来分享分享我的实现,免得以后忘了,那先看看效果(Demo在结尾有下载地址):


要达到的效果就是这么简单。

先说说思路吧:首先为联系人对象添加一个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源码下载







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ywl5320

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值