Android ListView快速定位(一)

方法一: SectionIndexer接口 + 索引列表

参考: http://www.apkbus.com/android-69999-1-1.html

所谓section 就是一组有共性的item, 比如由相同的字母开头

SectionIndexer接口主要的方法有:
图片标题
实现步骤:

1.给listview添加section

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public class MyAdapter extends BaseAdapter implements SectionIndexer , Filterable{

                private List<String> sections = new ArrayList<String>(); //保存section

                @Override

        public View getView(int position, View convertView, ViewGroup parent) {

                        //获取item控件

            。。。

            //添加section, 这里是将首字母相同的分为一个section
            //section用一个TextView实现,需要分组的时候显示,不需要的时候隐藏

            String label = filteredItems.get(position).get("cid");  
            char firstChar = label.toUpperCase().charAt(0);  
            if (position == 0) {

                viewholder.section.setVisibility(View.VISIBLE);
                viewholder.section.setText(label.substring(0, 1).toUpperCase());
                sections.add(label.substring(0, 1).toUpperCase());

            } else {

                String preLabel = filteredItems.get(position - 1).get("cid");  
                char preFirstChar = preLabel.toUpperCase().charAt(0);  
                if (firstChar != preFirstChar) {  

                    viewholder.section.setVisibility(View.VISIBLE);
                    viewholder.section.setText(label.substring(0, 1).toUpperCase());
                    sections.add(label.substring(0, 1).toUpperCase());

                } else {  

                    viewholder.section.setVisibility(View.GONE);  

                }  

            }
            return convertView;

        }


                @Override

        public Object[] getSections() {

            return  sections.toArray();

        }


        @Override
        public int getPositionForSection(int section) { 

            if (section == '!') { //这里第一行是个搜索框,用个"!"做个标记

                return 0;

            } else {  //其余的都按首字母查找,查找时都换成大写,用于忽略大小写匹配

                for (int i = 0; i < filteredItems.size(); i++) {  

                    String l = filteredItems.get(i).get("cid");  
                    char firstChar = l.toUpperCase().charAt(0);  
                    if (firstChar == section) {  

                        return i+1;  

                    }  

                }  

            }
            return -1;

        }


        @Override
        public int getSectionForPosition(int position) {

            return 0;

        }


}

2.创建索引列表
这个因人而异,看需求了。上面我的section是用首字母区分的,那么索引就用字母来做。
可以直接定死了26个字母。也可以调用adapter. getSections()获取到所有的section,生成索引。
关于生成索引,参考的例子中是做成了一个SideBar的控件,这个还有待研究,我只能看得懂,自己写不出来。

参考的例子中是:
```Java
@Override

 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
protected void onDraw(Canvas canvas) {

    Paint paint = new Paint();
    paint.setColor(color);
    paint.setTextSize(12);
    paint.setStyle(Style.FILL);    
    paint.setTextAlign(Paint.Align.CENTER);
    float widthCenter = getMeasuredWidth() / 2;
    if (l.length > 0) {

        float height = getMeasuredHeight() / l.length;
        for (int i = 0; i < l.length; i++) {

            if (i == 0 && type != 2) {

                canvas.drawBitmap(mbitmap, widthCenter - 7, (i + 1)* height - height / 2, paint);

            } else {

                canvas.drawText(String.valueOf(l[i]), widthCenter, (i + 1) * height, paint);

            }

        }

    }
    this.invalidate();
    super.onDraw(canvas);

}
1
2
3
3.索引关联listview的section
点击某个索引值的时候,调用getPositionForSection()获得改索引对应的第一个position,然后设置```Java
listview.setSelection(position);

该参考例子中的实现是:
OnTouch事件中获取SectionIndexer当前的position, 并将当前选中的section显示出来

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  @Override
    public boolean onTouchEvent(MotionEvent event) {

        super.onTouchEvent(event);
        int i = (int) event.getY();

        int idx = i / (getMeasuredHeight() / l.length);
        if (idx >= l.length) {

            idx = l.length - 1;

        } else if (idx < 0) {

            idx = 0;

        }
        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {

            setBackgroundResource(R.drawable.scrollbar_bg);

                           //显示当前选中的section
                           mDialogText.setVisibility(View.VISIBLE);                       

            if (idx == 0) {

                mDialogText.setText("Search");
                mDialogText.setTextSize(16);

            } else {

                mDialogText.setText(String.valueOf(l[idx]));
                mDialogText.setTextSize(34);

            }

            //获取sectionIndexer对象
            if (sectionIndexter == null) {

                sectionIndexter = (SectionIndexer) list.getAdapter();

            }

             //获取当前section对应的position
            int position = sectionIndexter.getPositionForSection(l[idx]);
            if (position == -1) {

                return true;

            }

                  //设置listview当前选中该position

            list.setSelection(position);

        } else {

            mDialogText.setVisibility(View.INVISIBLE);

        }

        if (event.getAction() == MotionEvent.ACTION_UP) {

            setBackgroundDrawable(new ColorDrawable(0x00000000));

        }
        return true;

    }

listview和显示当前section的textview都是外面activity传过来的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  public void setListView(ListView _list) {

        list = _list;
        HeaderViewListAdapter ha = (HeaderViewListAdapter) _list.getAdapter();
        MyAdapter ad = (MyAdapter)ha.getWrappedAdapter();
        sectionIndexter = (SectionIndexer)ad;


    }

    public void setTextView(TextView mDialogText) {

        this.mDialogText = mDialogText;

    }

效果图:
图片标题

原文地址:https://www.cnblogs.com/Free-Thinker/p/3632516.html