最近抽空写了一个小小的联系人,在主界面右侧添加了A-Z的快速索引栏,可以通过点击、滑动来快速定位联系人。源码没来得及做注释,就在这里简单说明下。
主界面是由一个listview和一个自定义的侧边栏界面:MyBladeView组成的。
1.主程序MainActivity:
只是简单的获取控件,设置相关的监听。需要注意的是,在对listview进行setAdapter时,要调用mListView.setFastScrollEnabled(false)和mListView.setVerticalScrollBarEnabled(false)方法,来将系统默认的快速定位关掉。
另外记得加权限:<uses-permission android:name="android.permission.READ_CONTACTS" />
2.自定义列表:MyListView:
public MyListView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub }
3.自定义适配器:MyListAdapter:
这里需要写一个listItem的布局文件:list_item.xml。然后在适配器的getView中进行处理,将得到的姓名、电话信息显示在每一个item上。当上一个人的首字母和当前人的首字母不一样时,就会在当前人的item中额外显示一个大写字母,详见getView方法。
alphaIndexer:存储列表中存在的A-Z索引字母,但是顺序是乱的。他的键值对并非按照1,2,3这样的顺序来存储。这就需要另外一个字符数组sections来进行有序存储。
sections = new String[alphaIndexer.size()]; for(int i = 0; i < b.length; i++){ if(alphaIndexer.containsKey(b[i])){ sections[num] = b[i]; num++; } }同时适配器需要提供一些公共方法让其他文件调用:
getSortKey:根据列表序号获得首字母。
getAlphaIndexer:根据首字母获得列表中第一个具有该首字母的item序号。
由于额外增加的大写字母会在单击该item时同时变亮,会很不美观。于是需要重写SelectionBoundsAdjuster方法,使得当单击一个item时,只有我想让他亮的地方他才会亮。
4.自定义listitem布局ItemHighLight:
在onFinishInflate()之中根据ID获得相应控件,然后在adjustListItemSelectionBounds设置要单击后会亮起的rect区域。
5.侧边索引栏MyBladeView:
其实现的功能有:
一:根据listview最顶端名字的首字母让侧边栏中的相应首字母背景出现小黑块。
通过MyListView的onScroll以及MyBladeView中的setIndicatorLocation方法实现:
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub Log.i(TAG,"MyListView: onScroll start: firstVisibleItem:"+firstVisibleItem+" visibleItemCount:" +visibleItemCount+" totalItemCount:"+totalItemCount); if(mAdapter != null){ String s = mAdapter.getSortKey(firstVisibleItem); Log.i(TAG,"MyListView: s is "+s); mBladeview.setIndicatorLocation(s); } }
public void setIndicatorLocation(String s){ int location = 0; for(int i = 0; i < sections.length; i++){ if(sections[i].equals(s)){ location = i; break; } } Log.i(TAG,"MyBladeView: setIndicatorLocation "+location); drawIndicatorRect(location); }
二:listview中包含的大写字母,在侧边栏中黑色显示,没有包含的字母,在侧边栏中蓝色显示。
通过setAbsentSections实现,该方法需要在onDraw中调用。
三:单击或拖动侧边栏字母,listview需要与之同步,侧边栏中被触碰到的字母必需同时是listview最顶端显示的字母。
通过重写dispatchTouchEvent来实现。其中的监听器在主程序中进行处理:
mBladeView = (MyBladeView)findViewById(R.id.blade_view); mBladeView.setOnSectionsTouchedListener(new OnSectionsTouchedListener() { @Override public void OnSectionsTouched(String s) { // TODO Auto-generated method stub if(adapter.getAlphaIndexer(s) != null){ int position = adapter.getAlphaIndexer(s); mListView.setSelection(position); } } });
四:单击或拖动侧边栏字母,屏幕中需要显示一个大的popupwindow,用来显示触碰到的是哪个字母,方便查看。
通过showPromptWindow方法实现。在dispatchTouchEvent中来进行window的显示以及消除。
现在只是大概弄出来一个框架,至于打电话,发短信,通话记录等功能,暂时还没有时间整理。打电话发短信只需要对list_item的布局进行调整,然后加入单击事件。或者再写一个Activity,当单击item之后直接跳过去,这样就可以在新的activity中为所欲为了。原生的contacts还有通话记录,以及通讯录分组的功能,是用viewpager实现的。如果要实现成源生contacts那样,就需要布一个更大的框架了。。。
源码地址:点击打开链接