android字母索引实现ListView定位

最近闲的很,没什么事干 ,在玩手机的时间看到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的宽高.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@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能够得到高度后再计算就可以.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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方法,这个方法就不用多说了吧,大家都知道是干什么的,直接上代码.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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

 

posted @   架构文摘  阅读(1776)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示