android学习笔记:联系人侧边栏的实现

最近抽空写了一个小小的联系人,在主界面右侧添加了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
	}

这个构造函数一定要加上,其他那两个单参数和三参数的删掉也没关系,不过至于为什么,我也不晓得了。。。ORZ。。。重写onScroll方法,当拖动联系人时,可以让侧边栏BladeView中的字母也有相应动作。其中的BladeView对象在MainActivity中传入。


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那样,就需要布一个更大的框架了。。。

源码地址:点击打开链接

你可能感兴趣的:(android学习笔记:联系人侧边栏的实现)