最近闲的很,没什么事干 ,在玩手机的时间看到android系统自带的那个通讯录软件对联系人的快速定位功能. 感觉这个功能也比较实用自己就试着自己去实现.
虽然网络上还是有大牛封闭好了的框架,但是如果自己来实现一下也是不错的, 个人比较喜欢自己写的东西,别人写好的东西可以拿来借鉴,还是不推荐看也不看直接拿
来用,代码可以复制,作者的思想就需要慢慢体会的.
基本介绍:
首先安卓本身已经提供一个接口来实现快速定位的, SectionIndexer接口共有三个方法.
Object[] getSections(); //返回所有的section
int getPositionForSection(int sectionIndex); //根据section索引返回一个position
int getSectionForPosition(int position); //与上面的方法正好相反 .
section可以理解为一个ListView中的一部分,比如在联系人进行分组将首字母相同的分为同一组,每一组就是一个section.
基本设计:
我将那些字母的列表看成是一个View这个View里面包含一个实现SectionIndexer接口的成员. 且定义一个回调接口用于在索引更改时通知更新ListView.
重写onMeasure(int,int)方法计算View的宽高.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(mSectionIndex == null){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return ;
}
if(mSections == null)
mSections = mSectionIndex.getSections();
int measureHeight ;
int measureWidth ;
int height = (int) (sectionHeight() * mSections.length ) + ( getPaddingTop() + getPaddingBottom() );
int width = sectionWidth() + getPaddingLeft() + getPaddingRight();
/**
* 根据布局参数来设置View的宽高.
* 如果布局参数的高或宽为LayoutParams.WRAP_CONTENT
* 则View的宽高分别为 width , height
* 否则直接根据布局参数的数值来设置
*/
LayoutParams lp = getLayoutParams();
if(lp.height != LayoutParams.WRAP_CONTENT)
height = lp.height;
if(lp.width != LayoutParams.WRAP_CONTENT)
width = lp.width;
/** */
measureHeight = ViewGroup.getChildMeasureSpec(heightMeasureSpec, 0,height);
measureWidth = ViewGroup.getChildMeasureSpec(widthMeasureSpec, 0, width);
setMeasuredDimension(measureWidth, measureHeight);
}
重写onLayout方法,重写该方法的原因是使所有的索引填满View. 不一定要重写onLayout方法,只要在View能够得到高度后再计算就可以.
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
/**
* view 的高度大于列表显示的高度, 在每一个字母之间加入一些间隔,
* 使每一个字母对齐,并填满整个view.
*/
int viewHeight = getHeight() - (getPaddingTop() + getPaddingBottom());
int originalHeight = mHeight * mSections.length;
int overHeight = viewHeight - originalHeight;
if(overHeight <= 0) return ;
mAlphaInterval = overHeight / (mSections.length);
}
重写onDraw方法,这个方法就不用多说了吧,大家都知道是干什么的,直接上代码.
@Override
protected void onDraw(Canvas canvas) {
if(mSectionIndex == null)
return ;
int height = getHeight();
int widht = getWidth();
//画背景
if(mBackground){
RectF round = new RectF(0, 0, widht, height);
canvas.drawRect(round, mBackgroundPaint);
}
//画字母
float textheight = mAlphaPaint.descent()- mAlphaPaint.ascent();
float y = textheight / 1.5f + getPaddingTop(); //第一个字母偏移 .
float x = getPaddingLeft() ;
for(int i = 0; i < mSections.length ; i++){
if(mCurrentSection == i)
mAlphaPaint.setColor(Color.BLUE);
else
mAlphaPaint.setColor(Color.WHITE);
y += mAlphaPadding + mAlphaInterval;
canvas.drawText(mSections[i].toString() , x, y, mAlphaPaint);
y += mAlphaPadding + textheight ;
}
}
效果图:

最后还包含一些辅助方法,就不一一例举的大家下载源码一看便知.
源码下载 :
http://pan.baidu.com/s/1gdw1gyf