Android手机联系人带字母索引的快速查找

时间:2021-09-14 06:34:45

喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。
效果图如下:

Android手机联系人带字母索引的快速查找

第一步:mainactivity的代码如下:

?
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package net.loonggg.test;
 
import java.util.arraylist;
import java.util.arrays;
import java.util.hashmap;
import java.util.list;
import java.util.treeset;
 
import android.os.bundle;
import android.app.activity;
import android.graphics.color;
import android.view.motionevent;
import android.view.view;
import android.view.view.ontouchlistener;
import android.view.window;
import android.widget.linearlayout;
import android.widget.listview;
import android.widget.textview;
import android.widget.linearlayout.layoutparams;
 
public class mainactivity extends activity {
  private hashmap<string, integer> selector;// 存放含有索引字母的位置
  private linearlayout layoutindex;
  private listview listview;
  private textview tv_show;
  private listviewadapter adapter;
  private string[] indexstr = { "#", "a", "b", "c", "d", "e", "f", "g", "h",
      "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
      "v", "w", "x", "y", "z" };
  private list<person> persons = null;
  private list<person> newpersons = new arraylist<person>();
  private int height;// 字体高度
  private boolean flag = false;
 
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    // 去标题栏
    requestwindowfeature(window.feature_no_title);
    setcontentview(r.layout.activity_main);
    layoutindex = (linearlayout) this.findviewbyid(r.id.layout);
    layoutindex.setbackgroundcolor(color.parsecolor("#00ffffff"));
    listview = (listview) findviewbyid(r.id.listview);
    tv_show = (textview) findviewbyid(r.id.tv);
    tv_show.setvisibility(view.gone);
    setdata();
    string[] allnames = sortindex(persons);
    sortlist(allnames);
 
    selector = new hashmap<string, integer>();
    for (int j = 0; j < indexstr.length; j++) {// 循环字母表,找出newpersons中对应字母的位置
      for (int i = 0; i < newpersons.size(); i++) {
        if (newpersons.get(i).getname().equals(indexstr[j])) {
          selector.put(indexstr[j], i);
        }
      }
 
    }
    adapter = new listviewadapter(this, newpersons);
    listview.setadapter(adapter);
  }
 
  /**
   * 重新排序获得一个新的list集合
   *
   * @param allnames
   */
  private void sortlist(string[] allnames) {
    for (int i = 0; i < allnames.length; i++) {
      if (allnames[i].length() != 1) {
        for (int j = 0; j < persons.size(); j++) {
          if (allnames[i].equals(persons.get(j).getpinyinname())) {
            person p = new person(persons.get(j).getname(), persons
                .get(j).getpinyinname());
            newpersons.add(p);
          }
        }
      } else {
        newpersons.add(new person(allnames[i]));
      }
    }
  }
 
  @override
  public void onwindowfocuschanged(boolean hasfocus) {
    // 在oncreate里面执行下面的代码没反应,因为oncreate里面得到的getheight=0
    if (!flag) {// 这里为什么要设置个flag进行标记,我这里不先告诉你们,请读者研究,因为这对你们以后的开发有好处
      height = layoutindex.getmeasuredheight() / indexstr.length;
      getindexview();
      flag = true;
    }
  }
 
  /**
   * 获取排序后的新数据
   *
   * @param persons
   * @return
   */
  public string[] sortindex(list<person> persons) {
    treeset<string> set = new treeset<string>();
    // 获取初始化数据源中的首字母,添加到set中
    for (person person : persons) {
      set.add(stringhelper.getpinyinheadchar(person.getname()).substring(
          0, 1));
    }
    // 新数组的长度为原数据加上set的大小
    string[] names = new string[persons.size() + set.size()];
    int i = 0;
    for (string string : set) {
      names[i] = string;
      i++;
    }
    string[] pinyinnames = new string[persons.size()];
    for (int j = 0; j < persons.size(); j++) {
      persons.get(j).setpinyinname(
          stringhelper
              .getpingyin(persons.get(j).getname().tostring()));
      pinyinnames[j] = stringhelper.getpingyin(persons.get(j).getname()
          .tostring());
    }
    // 将原数据拷贝到新数据中
    system.arraycopy(pinyinnames, 0, names, set.size(), pinyinnames.length);
    // 自动按照首字母排序
    arrays.sort(names, string.case_insensitive_order);
    return names;
  }
 
  /**
   * 绘制索引列表
   */
  public void getindexview() {
    linearlayout.layoutparams params = new layoutparams(
        layoutparams.wrap_content, height);
    for (int i = 0; i < indexstr.length; i++) {
      final textview tv = new textview(this);
      tv.setlayoutparams(params);
      tv.settext(indexstr[i]);
      tv.setpadding(10, 0, 10, 0);
      layoutindex.addview(tv);
      layoutindex.setontouchlistener(new ontouchlistener() {
 
        @override
        public boolean ontouch(view v, motionevent event)
 
        {
          float y = event.gety();
          int index = (int) (y / height);
          if (index > -1 && index < indexstr.length) {// 防止越界
            string key = indexstr[index];
            if (selector.containskey(key)) {
              int pos = selector.get(key);
              if (listview.getheaderviewscount() > 0) {// 防止listview有标题栏,本例中没有。
                listview.setselectionfromtop(
                    pos + listview.getheaderviewscount(), 0);
              } else {
                listview.setselectionfromtop(pos, 0);// 滑动到第一项
              }
              tv_show.setvisibility(view.visible);
              tv_show.settext(indexstr[index]);
            }
          }
          switch (event.getaction()) {
          case motionevent.action_down:
            layoutindex.setbackgroundcolor(color
                .parsecolor("#606060"));
            break;
 
          case motionevent.action_move:
 
            break;
          case motionevent.action_up:
            layoutindex.setbackgroundcolor(color
                .parsecolor("#00ffffff"));
            tv_show.setvisibility(view.gone);
            break;
          }
          return true;
        }
      });
    }
  }
 
  /**
   * 设置模拟数据
   */
  private void setdata() {
    persons = new arraylist<person>();
    person p1 = new person("耿琦");
    persons.add(p1);
    person p2 = new person("王宝强");
    persons.add(p2);
    person p3 = new person("柳岩");
    persons.add(p3);
    person p4 = new person("文章");
    persons.add(p4);
    person p5 = new person("马伊琍");
    persons.add(p5);
    person p6 = new person("李晨");
    persons.add(p6);
    person p7 = new person("张馨予");
    persons.add(p7);
    person p8 = new person("韩红");
    persons.add(p8);
    person p9 = new person("韩寒");
    persons.add(p9);
    person p10 = new person("丹丹");
    persons.add(p10);
    person p11 = new person("丹凤眼");
    persons.add(p11);
    person p12 = new person("哈哈");
    persons.add(p12);
    person p13 = new person("萌萌");
    persons.add(p13);
    person p14 = new person("蒙混");
    persons.add(p14);
    person p15 = new person("烟花");
    persons.add(p15);
    person p16 = new person("眼黑");
    persons.add(p16);
    person p17 = new person("许三多");
    persons.add(p17);
    person p18 = new person("程咬金");
    persons.add(p18);
    person p19 = new person("程哈哈");
    persons.add(p19);
    person p20 = new person("爱死你");
    persons.add(p20);
    person p21 = new person("阿莱");
    persons.add(p21);
 
  }
 
}

 此activity的布局文件如下:

?
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
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="match_parent"
  android:background="#ffffff"
  android:orientation="vertical" >
 
  <textview
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:text="列表显示"
    android:textcolor="#000000"
    android:textsize="16sp" />
 
  <framelayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" >
 
    <listview
      android:id="@+id/listview"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:cachecolorhint="#00000000"
      android:fadingedge="none"
      android:scrollbars="none" >
    </listview>
 
    <textview
      android:id="@+id/tv"
      android:layout_width="60dp"
      android:layout_height="60dp"
      android:layout_gravity="center"
      android:background="#f0606060"
      android:gravity="center"
      android:text="a"
      android:textcolor="#ffffff"
      android:textsize="30sp" />
 
    <linearlayout
      android:id="@+id/layout"
      android:layout_width="wrap_content"
      android:layout_height="fill_parent"
      android:layout_gravity="right"
      android:background="#d7d7d7"
      android:gravity="center"
      android:orientation="vertical" >
    </linearlayout>
  </framelayout>
 
</linearlayout>

第二步:自定义了一个adapter,代码如下:

?
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
package net.loonggg.test;
 
import java.util.list;
 
import android.content.context;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.baseadapter;
import android.widget.textview;
 
public class listviewadapter extends baseadapter {
  private context context;
  private list<person> list;
  private viewholder viewholder;
 
  public listviewadapter(context context, list<person> list) {
    this.context = context;
    this.list = list;
  }
 
  @override
  public int getcount() {
    return list.size();
  }
 
  @override
  public object getitem(int position) {
    return list.get(position);
  }
 
  @override
  public long getitemid(int position) {
    return position;
  }
 
  @override
  public boolean isenabled(int position) {
    // todo auto-generated method stub
    if (list.get(position).getname().length() == 1)// 如果是字母索引
      return false;// 表示不能点击
    return super.isenabled(position);
  }
 
  @override
  public view getview(int position, view convertview, viewgroup parent) {
    string item = list.get(position).getname();
    viewholder = new viewholder();
    if (item.length() == 1) {
      convertview = layoutinflater.from(context).inflate(r.layout.index,
          null);
      viewholder.indextv = (textview) convertview
          .findviewbyid(r.id.indextv);
    } else {
      convertview = layoutinflater.from(context).inflate(r.layout.item,
          null);
      viewholder.itemtv = (textview) convertview
          .findviewbyid(r.id.itemtv);
    }
    if (item.length() == 1) {
      viewholder.indextv.settext(list.get(position).getname());
    } else {
      viewholder.itemtv.settext(list.get(position).getname());
    }
    return convertview;
  }
 
  private class viewholder {
    private textview indextv;
    private textview itemtv;
  }
 
}

第三步:用到的listview中的子布局文件如下:
1、index.xml布局文件代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="#9c9c9c"
  android:orientation="vertical"
  android:paddingbottom="5dp"
  android:paddingleft="10dp"
  android:paddingtop="5dp" >
 
  <textview
    android:id="@+id/indextv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textcolor="#0f0f0f" />
 
</linearlayout>

2、item.xml布局文件代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="#ffffff"
  android:orientation="vertical"
  android:paddingbottom="5dp"
  android:paddingleft="20dp"
  android:paddingtop="5dp" >
 
  <textview
    android:id="@+id/itemtv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textcolor="#000000"
    android:textsize="20sp" />
 
</linearlayout>

第四步:用到的实体类及工具类如下:
1、person.java代码如下:

?
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
package net.loonggg.test;
 
public class person {
  private string name;
  private string pinyinname;
 
  public person(string name) {
    super();
    this.name = name;
  }
 
  public person(string name, string pinyinname) {
    super();
    this.name = name;
    this.pinyinname = pinyinname;
  }
 
  public string getname() {
    return name;
  }
 
  public void setname(string name) {
    this.name = name;
  }
 
  public string getpinyinname() {
    return pinyinname;
  }
 
  public void setpinyinname(string pinyinname) {
    this.pinyinname = pinyinname;
  }
 
}

2、工具类代码如下:

?
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
package net.loonggg.test;
 
import net.sourceforge.pinyin4j.pinyinhelper;
import net.sourceforge.pinyin4j.format.hanyupinyincasetype;
import net.sourceforge.pinyin4j.format.hanyupinyinoutputformat;
import net.sourceforge.pinyin4j.format.hanyupinyintonetype;
import net.sourceforge.pinyin4j.format.hanyupinyinvchartype;
import net.sourceforge.pinyin4j.format.exception.badhanyupinyinoutputformatcombination;
 
public class stringhelper {
  /**
   * 得到 全拼
   *
   * @param src
   * @return
   */
  public static string getpingyin(string src) {
    char[] t1 = null;
    t1 = src.tochararray();
    string[] t2 = new string[t1.length];
    hanyupinyinoutputformat t3 = new hanyupinyinoutputformat();
    t3.setcasetype(hanyupinyincasetype.lowercase);
    t3.settonetype(hanyupinyintonetype.without_tone);
    t3.setvchartype(hanyupinyinvchartype.with_v);
    string t4 = "";
    int t0 = t1.length;
    try {
      for (int i = 0; i < t0; i++) {
        // 判断是否为汉字字符
        if (java.lang.character.tostring(t1[i]).matches(
            "[\\u4e00-\\u9fa5]+")) {
          t2 = pinyinhelper.tohanyupinyinstringarray(t1[i], t3);
          t4 += t2[0];
        } else {
          t4 += java.lang.character.tostring(t1[i]);
        }
      }
      return t4;
    } catch (badhanyupinyinoutputformatcombination e1) {
      e1.printstacktrace();
    }
    return t4;
  }
 
  /**
   * 得到首字母
   *
   * @param str
   * @return
   */
  public static string getheadchar(string str) {
 
    string convert = "";
    char word = str.charat(0);
    string[] pinyinarray = pinyinhelper.tohanyupinyinstringarray(word);
    if (pinyinarray != null) {
      convert += pinyinarray[0].charat(0);
    } else {
      convert += word;
    }
    return convert.touppercase();
  }
   
  /**
   * 得到中文首字母缩写
   *
   * @param str
   * @return
   */
  public static string getpinyinheadchar(string str) {
 
    string convert = "";
    for (int j = 0; j < str.length(); j++) {
      char word = str.charat(j);
      string[] pinyinarray = pinyinhelper.tohanyupinyinstringarray(word);
      if (pinyinarray != null) {
        convert += pinyinarray[0].charat(0);
      } else {
        convert += word;
      }
    }
    return convert.touppercase();
  }
}

到这里就完事,非常简单吧!