├── AndroidManifest.xml
├── README.md
├── ic_launcher-web.png
├── image
└── 0.jpg
├── libs
└── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ ├── emotionstore_progresscancelbtn.png
│ ├── ic_launcher.png
│ ├── search_bar_edit_normal.9.png
│ ├── search_bar_edit_pressed.9.png
│ ├── search_bar_icon_normal.png
│ └── show_head_toast_bg.9.PNG
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable
│ ├── search_bar_edit_selector.xml
│ └── sidebar_background.xml
├── layout
│ ├── activity_main.xml
│ └── item.xml
├── menu
│ └── activity_main.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── values
│ ├── arrays.xml
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── example
├── adapter
└── SortAdapter.java
├── sortlistview
└── MainActivity.java
├── utils
├── CharacterParser.java
└── PinyinComparator.java
├── voo
└── SortModel.java
└── widget
├── ClearEditText.java
└── SideBar.java
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # name_indexbar
2 | Name Index Bar(右侧26个英文字母列表的可根据首字母定位的ListView)
3 |
4 | 效果图:
5 | 
6 |
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/ic_launcher-web.png
--------------------------------------------------------------------------------
/image/0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/image/0.jpg
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/emotionstore_progresscancelbtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/emotionstore_progresscancelbtn.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/search_bar_edit_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/search_bar_edit_normal.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/search_bar_edit_pressed.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/search_bar_edit_pressed.9.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/search_bar_icon_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/search_bar_icon_normal.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/show_head_toast_bg.9.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-hdpi/show_head_toast_bg.9.PNG
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/name_indexbar/c9df8c56c542bfbc4d2c5ee3e8c7f66a3a874512/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable/search_bar_edit_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/drawable/sidebar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
18 |
19 |
22 |
23 |
29 |
30 |
31 |
41 |
42 |
43 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
20 |
21 |
22 |
34 |
35 |
--------------------------------------------------------------------------------
/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values/arrays.xml:
--------------------------------------------------------------------------------
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 | - BOBO
41 | - Jobs
42 | - 动力火车
43 | - 伍佰
44 | - #蔡依林
45 | - $797835344$
46 | - Jack
47 | - ~夏先生
48 |
49 |
50 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #99C60000
4 | #ffffffff
5 | #336598
6 | #E0E0E0
7 | #454545
8 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SortListView
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/com/example/adapter/SortAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.adapter;
2 |
3 | import java.util.List;
4 | import com.example.sortlistview.R;
5 | import com.example.voo.SortModel;
6 | import android.content.Context;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.BaseAdapter;
11 | import android.widget.SectionIndexer;
12 | import android.widget.TextView;
13 |
14 | /**
15 | * 按照名称首字母进行排序的adapter
16 | * @author Jack
17 | * @version 创建时间:2014年8月1日 下午4:02:37
18 | */
19 | public class SortAdapter extends BaseAdapter implements SectionIndexer {
20 |
21 | private List list = null;
22 | private Context mContext;
23 |
24 | public SortAdapter(Context mContext, List list) {
25 | this.mContext = mContext;
26 | this.list = list;
27 | }
28 |
29 | /**
30 | * 当ListView数据发生变化时,调用此方法来更新ListView
31 | *
32 | * @param list
33 | */
34 | public void updateListView(List list) {
35 | this.list = list;
36 | notifyDataSetChanged();
37 | }
38 |
39 | public int getCount() {
40 | return this.list.size();
41 | }
42 |
43 | public Object getItem(int position) {
44 | return list.get(position);
45 | }
46 |
47 | public long getItemId(int position) {
48 | return position;
49 | }
50 |
51 | public View getView(final int position, View view, ViewGroup arg2) {
52 | ViewHolder viewHolder = null;
53 | final SortModel mContent = list.get(position);
54 | if (view == null) {
55 | viewHolder = new ViewHolder();
56 | view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
57 | viewHolder.tvTitle = (TextView) view.findViewById(R.id.title);
58 | viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog);
59 | view.setTag(viewHolder);
60 | } else {
61 | viewHolder = (ViewHolder) view.getTag();
62 | }
63 |
64 | // 根据position获取分类的首字母的Char ascii值
65 | int section = getSectionForPosition(position);
66 |
67 | // 如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
68 | if (position == getPositionForSection(section)) {
69 | viewHolder.tvLetter.setVisibility(View.VISIBLE);
70 | viewHolder.tvLetter.setText(mContent.getSortLetters());
71 | } else {
72 | viewHolder.tvLetter.setVisibility(View.GONE);
73 | }
74 | viewHolder.tvTitle.setText(this.list.get(position).getName());
75 | return view;
76 |
77 | }
78 |
79 | final static class ViewHolder {
80 | TextView tvLetter;
81 | TextView tvTitle;
82 | }
83 |
84 | /**
85 | * 根据ListView的当前位置获取分类的首字母的Char ascii值
86 | */
87 | public int getSectionForPosition(int position) {
88 | return list.get(position).getSortLetters().charAt(0);
89 | }
90 |
91 | /**
92 | * 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
93 | */
94 | public int getPositionForSection(int section) {
95 | for (int i = 0; i < getCount(); i++) {
96 | String sortStr = list.get(i).getSortLetters();
97 | char firstChar = sortStr.toUpperCase().charAt(0);
98 | if (firstChar == section) {
99 | return i;
100 | }
101 | }
102 |
103 | return -1;
104 | }
105 |
106 | /**
107 | * 提取英文的首字母,非英文字母用#代替。
108 | *
109 | * @param str
110 | * @return
111 | */
112 | private String getAlpha(String str) {
113 | String sortStr = str.trim().substring(0, 1).toUpperCase();
114 | // 正则表达式,判断首字母是否是英文字母
115 | if (sortStr.matches("[A-Z]")) {
116 | return sortStr;
117 | } else {
118 | return "#";
119 | }
120 | }
121 |
122 | @Override
123 | public Object[] getSections() {
124 | return null;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/com/example/sortlistview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.sortlistview;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 | import android.app.Activity;
7 | import android.os.Bundle;
8 | import android.text.Editable;
9 | import android.text.TextUtils;
10 | import android.text.TextWatcher;
11 | import android.view.View;
12 | import android.widget.AdapterView;
13 | import android.widget.AdapterView.OnItemClickListener;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 | import com.example.adapter.SortAdapter;
18 | import com.example.utils.CharacterParser;
19 | import com.example.utils.PinyinComparator;
20 | import com.example.voo.SortModel;
21 | import com.example.widget.ClearEditText;
22 | import com.example.widget.SideBar;
23 | import com.example.widget.SideBar.OnTouchingLetterChangedListener;
24 |
25 | public class MainActivity extends Activity {
26 |
27 | private ListView sortListView;
28 | private SideBar sideBar;
29 | private TextView dialog;
30 | private SortAdapter adapter;
31 | private ClearEditText mClearEditText;
32 | /** 汉字转换成拼音的类 */
33 | private CharacterParser characterParser;
34 | private List sourceDataList;
35 | /** 根据拼音来排列ListView里面的数据类 */
36 | private PinyinComparator pinyinComparator;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_main);
42 | initViews();
43 | }
44 |
45 | private void initViews() {
46 | // 实例化汉字转拼音类
47 | characterParser = CharacterParser.getInstance();
48 | pinyinComparator = new PinyinComparator();
49 | sideBar = (SideBar) findViewById(R.id.sidrbar);
50 | dialog = (TextView) findViewById(R.id.dialog);
51 | sideBar.setTextView(dialog);
52 | // 设置右侧触摸监听
53 | sideBar.setOnTouchingLetterChangedListener(new OnTouchingLetterChangedListener() {
54 |
55 | @Override
56 | public void onTouchingLetterChanged(String s) {
57 | // 该字母首次出现的位置
58 | int position = adapter.getPositionForSection(s.charAt(0));
59 | if (position != -1) {
60 | sortListView.setSelection(position);
61 | }
62 | }
63 | });
64 |
65 | //单击名称列表后toast提示
66 | sortListView = (ListView) findViewById(R.id.name_listview);
67 | sortListView.setOnItemClickListener(new OnItemClickListener() {
68 |
69 | @Override
70 | public void onItemClick(AdapterView> parent, View view,
71 | int position, long id) {
72 | // 这里要利用adapter.getItem(position)来获取当前position所对应的对象
73 | Toast.makeText(getApplication(),
74 | ((SortModel) adapter.getItem(position)).getName(),
75 | Toast.LENGTH_SHORT).show();
76 | }
77 | });
78 | sourceDataList = filledData(getResources().getStringArray(R.array.data));
79 | // 根据a-z进行排序源数据
80 | Collections.sort(sourceDataList, pinyinComparator);
81 | adapter = new SortAdapter(this, sourceDataList);
82 | sortListView.setAdapter(adapter);
83 |
84 | //查询框设置监听
85 | mClearEditText = (ClearEditText) findViewById(R.id.filter_edit);
86 | // 根据输入框输入值的改变来过滤搜索
87 | mClearEditText.addTextChangedListener(new TextWatcher() {
88 |
89 | @Override
90 | public void onTextChanged(CharSequence s, int start, int before,
91 | int count) {
92 | // 当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
93 | filterData(s.toString());
94 | }
95 |
96 | @Override
97 | public void beforeTextChanged(CharSequence s, int start, int count,
98 | int after) {
99 |
100 | }
101 |
102 | @Override
103 | public void afterTextChanged(Editable s) {
104 | }
105 | });
106 | }
107 |
108 | /**
109 | * 为ListView填充数据
110 | * @param data
111 | * @return
112 | */
113 | private List filledData(String[] data) {
114 |
115 | List mSortList = new ArrayList();
116 | for (int i = 0; i < data.length; i++) {
117 |
118 | SortModel sortModel = new SortModel();
119 | sortModel.setName(data[i]);
120 | // 汉字转换成拼音
121 | String pinyin = characterParser.getSelling(data[i]);
122 | String sortString = pinyin.substring(0, 1).toUpperCase();
123 |
124 | // 正则表达式,判断首字母是否是英文字母
125 | if (sortString.matches("[A-Z]")) {
126 | sortModel.setSortLetters(sortString.toUpperCase());
127 | } else {
128 | sortModel.setSortLetters("#");
129 | }
130 | mSortList.add(sortModel);
131 | }
132 | return mSortList;
133 | }
134 |
135 | /**
136 | * 根据输入框中的值来过滤数据源,截取含有查询字符串的数据
137 | * @param filterStr 查询字符串
138 | */
139 | private void filterData(String filterStr) {
140 |
141 | List filterDataList = new ArrayList();
142 | if (TextUtils.isEmpty(filterStr)) {
143 |
144 | filterDataList = sourceDataList;
145 | } else {
146 |
147 | filterDataList.clear();
148 | for (SortModel sortModel : sourceDataList) {
149 |
150 | String name = sortModel.getName();
151 | if (name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())) {
152 |
153 | filterDataList.add(sortModel);
154 | }
155 | }
156 | }
157 | // 根据a-z进行排序
158 | Collections.sort(filterDataList, pinyinComparator);
159 | adapter.updateListView(filterDataList);
160 | }
161 | }
162 |
163 |
--------------------------------------------------------------------------------
/src/com/example/utils/CharacterParser.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | /**
4 | * Java汉字转换为拼音工具类
5 | */
6 | public class CharacterParser {
7 |
8 | private static int[] pinYinValue = new int[] { -20319, -20317, -20304,
9 | -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051,
10 | -20036, -20032, -20026, -20002, -19990, -19986, -19982, -19976,
11 | -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746,
12 | -19741, -19739, -19728, -19725, -19715, -19540, -19531, -19525,
13 | -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281,
14 | -19275, -19270, -19263, -19261, -19249, -19243, -19242, -19238,
15 | -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018,
16 | -19006, -19003, -18996, -18977, -18961, -18952, -18783, -18774,
17 | -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710,
18 | -18697, -18696, -18526, -18518, -18501, -18490, -18478, -18463,
19 | -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211,
20 | -18201, -18184, -18183, -18181, -18012, -17997, -17988, -17970,
21 | -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759,
22 | -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
23 | -17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433,
24 | -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915,
25 | -16733, -16708, -16706, -16689, -16664, -16657, -16647, -16474,
26 | -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427,
27 | -16423, -16419, -16412, -16407, -16403, -16401, -16393, -16220,
28 | -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169,
29 | -16158, -16155, -15959, -15958, -15944, -15933, -15920, -15915,
30 | -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661,
31 | -15659, -15652, -15640, -15631, -15625, -15454, -15448, -15436,
32 | -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375,
33 | -15369, -15363, -15362, -15183, -15180, -15165, -15158, -15153,
34 | -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128,
35 | -15121, -15119, -15117, -15110, -15109, -14941, -14937, -14933,
36 | -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908,
37 | -14902, -14894, -14889, -14882, -14873, -14871, -14857, -14678,
38 | -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594,
39 | -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
40 | -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137,
41 | -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097,
42 | -14094, -14092, -14090, -14087, -14083, -13917, -13914, -13910,
43 | -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859,
44 | -13847, -13831, -13658, -13611, -13601, -13406, -13404, -13400,
45 | -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356,
46 | -13343, -13340, -13329, -13326, -13318, -13147, -13138, -13120,
47 | -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060,
48 | -12888, -12875, -12871, -12860, -12858, -12852, -12849, -12838,
49 | -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585,
50 | -12556, -12359, -12346, -12320, -12300, -12120, -12099, -12089,
51 | -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831,
52 | -11798, -11781, -11604, -11589, -11536, -11358, -11340, -11339,
53 | -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045,
54 | -11041, -11038, -11024, -11020, -11019, -11018, -11014, -10838,
55 | -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544,
56 | -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309,
57 | -10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256,
58 | -10254 };
59 | public static String[] pystr = new String[] { "a", "ai", "an", "ang", "ao",
60 | "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi",
61 | "bian", "biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai",
62 | "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang",
63 | "chao", "che", "chen", "cheng", "chi", "chong", "chou", "chu",
64 | "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong",
65 | "cou", "cu", "cuan", "cui", "cun", "cuo", "da", "dai", "dan",
66 | "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding",
67 | "diu", "dong", "dou", "du", "duan", "dui", "dun", "duo", "e", "en",
68 | "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu",
69 | "ga", "gai", "gan", "gang", "gao", "ge", "gei", "gen", "geng",
70 | "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun",
71 | "guo", "ha", "hai", "han", "hang", "hao", "he", "hei", "hen",
72 | "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui",
73 | "hun", "huo", "ji", "jia", "jian", "jiang", "jiao", "jie", "jin",
74 | "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai",
75 | "kan", "kang", "kao", "ke", "ken", "keng", "kong", "kou", "ku",
76 | "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai",
77 | "lan", "lang", "lao", "le", "lei", "leng", "li", "lia", "lian",
78 | "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu",
79 | "lv", "luan", "lue", "lun", "luo", "ma", "mai", "man", "mang",
80 | "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie",
81 | "min", "ming", "miu", "mo", "mou", "mu", "na", "nai", "nan",
82 | "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang",
83 | "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan",
84 | "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei",
85 | "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po",
86 | "pu", "qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing",
87 | "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao",
88 | "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui",
89 | "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen",
90 | "seng", "sha", "shai", "shan", "shang", "shao", "she", "shen",
91 | "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang",
92 | "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui",
93 | "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng",
94 | "ti", "tian", "tiao", "tie", "ting", "tong", "tou", "tu", "tuan",
95 | "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen",
96 | "weng", "wo", "wu", "xi", "xia", "xian", "xiang", "xiao", "xie",
97 | "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya",
98 | "yan", "yang", "yao", "ye", "yi", "yin", "ying", "yo", "yong",
99 | "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang",
100 | "zao", "ze", "zei", "zen", "zeng", "zha", "zhai", "zhan", "zhang",
101 | "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu",
102 | "zhua", "zhuai", "zhuan", "zhuang", "zhui", "zhun", "zhuo", "zi",
103 | "zong", "zou", "zu", "zuan", "zui", "zun", "zuo" };
104 | private StringBuilder buffer;
105 | private String resource;
106 | private static CharacterParser characterParser = new CharacterParser();
107 |
108 | public static CharacterParser getInstance() {
109 | return characterParser;
110 | }
111 |
112 | public String getResource() {
113 | return resource;
114 | }
115 |
116 | public void setResource(String resource) {
117 | this.resource = resource;
118 | }
119 |
120 | /**
121 | * 汉字转成ASCII码
122 | * @param chs 汉字
123 | * @return 对应汉字的ascii码
124 | */
125 | private int getChsAscii(String chs) {
126 |
127 | int asc = 0;
128 | try {
129 | byte[] bytes = chs.getBytes("gb2312");
130 | if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
131 | throw new RuntimeException("illegal resource string");
132 | }
133 | if (bytes.length == 1) {
134 | asc = bytes[0];
135 | }
136 | if (bytes.length == 2) {
137 | int hightByte = 256 + bytes[0];
138 | int lowByte = 256 + bytes[1];
139 | asc = (256 * hightByte + lowByte) - 256 * 256;
140 | }
141 | } catch (Exception e) {
142 | System.out
143 | .println("ERROR:ChineseSpelling.class-getChsAscii(String chs)"
144 | + e);
145 | }
146 | return asc;
147 | }
148 |
149 | /**
150 | * 单字解析
151 | *
152 | * @param str
153 | * @return
154 | */
155 | public String convert(String str) {
156 | String result = null;
157 | int ascii = getChsAscii(str);
158 | if (ascii > 0 && ascii < 160) {
159 | result = String.valueOf((char) ascii);
160 | } else {
161 | for (int i = (pinYinValue.length - 1); i >= 0; i--) {
162 | if (pinYinValue[i] <= ascii) {
163 | result = pystr[i];
164 | break;
165 | }
166 | }
167 | }
168 | return result;
169 | }
170 |
171 | /**
172 | * 词组解析
173 | *
174 | * @param chs
175 | * @return
176 | */
177 | public String getSelling(String chs) {
178 | String key, value;
179 | buffer = new StringBuilder();
180 | for (int i = 0; i < chs.length(); i++) {
181 | key = chs.substring(i, i + 1);
182 | if (key.getBytes().length >= 2) {
183 | value = (String) convert(key);
184 | if (value == null) {
185 | value = "unknown";
186 | }
187 | } else {
188 | value = key;
189 | }
190 | buffer.append(value);
191 | }
192 | return buffer.toString();
193 | }
194 |
195 | public String getSpelling() {
196 | return this.getSelling(this.getResource());
197 | }
198 | }
--------------------------------------------------------------------------------
/src/com/example/utils/PinyinComparator.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.util.Comparator;
4 | import com.example.voo.SortModel;
5 |
6 | /**
7 | * 用户名称的比较器
8 | * @author Jack
9 | * @version 创建时间:2014-2-6 下午3:51:57
10 | */
11 | public class PinyinComparator implements Comparator {
12 |
13 | public int compare(SortModel o1, SortModel o2) {
14 |
15 | if (o1.getSortLetters().equals("@") || o2.getSortLetters().equals("#")) {
16 | return -1;
17 | } else if (o1.getSortLetters().equals("#") || o2.getSortLetters().equals("@")) {
18 | return 1;
19 | } else {
20 | return o1.getSortLetters().compareTo(o2.getSortLetters());
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/com/example/voo/SortModel.java:
--------------------------------------------------------------------------------
1 | package com.example.voo;
2 |
3 | /**
4 | * 需要排列的数据
5 | * @author Jack
6 | * @version 创建时间:2014-2-6 下午3:48:21
7 | */
8 | public class SortModel {
9 |
10 | private String name; //显示的数据
11 | private String sortLetters; //显示数据拼音的首字母
12 |
13 | public String getName() {
14 | return name;
15 | }
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 | public String getSortLetters() {
20 | return sortLetters;
21 | }
22 | public void setSortLetters(String sortLetters) {
23 | this.sortLetters = sortLetters;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/com/example/widget/ClearEditText.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import com.example.sortlistview.R;
4 | import android.content.Context;
5 | import android.graphics.drawable.Drawable;
6 | import android.text.Editable;
7 | import android.text.TextWatcher;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.View.OnFocusChangeListener;
12 | import android.widget.EditText;
13 |
14 | /**
15 | * 有删除按钮的输入框
16 | * @author Jack
17 | * @version 创建时间:2014-2-6 下午3:42:47
18 | */
19 | public class ClearEditText extends EditText implements OnFocusChangeListener, TextWatcher {
20 |
21 | /** 删除按钮的引用 */
22 | private Drawable mClearDrawable;
23 |
24 | public ClearEditText(Context context) {
25 | this(context, null);
26 | }
27 |
28 | public ClearEditText(Context context, AttributeSet attrs) {
29 | // 这里构造方法也很重要,不加这个很多属性不能再XML里面定义
30 | this(context, attrs, android.R.attr.editTextStyle);
31 | }
32 |
33 | public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
34 | super(context, attrs, defStyle);
35 | init();
36 | }
37 |
38 | private void init() {
39 | // 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
40 | mClearDrawable = getCompoundDrawables()[2];
41 | if (mClearDrawable == null) {
42 | mClearDrawable = getResources().getDrawable(R.drawable.emotionstore_progresscancelbtn);
43 | }
44 | mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
45 | setClearIconVisible(false);
46 | setOnFocusChangeListener(this);
47 | addTextChangedListener(this);
48 | }
49 |
50 | /**
51 | * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件 当我们按下的位置
52 | * 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度
53 | * 和 EditText的宽度 - 图标到控件右边的间距之间
54 | * 我们就算点击了图标,竖直方向没有考虑
55 | */
56 | @Override
57 | public boolean onTouchEvent(MotionEvent event) {
58 |
59 | if (getCompoundDrawables()[2] != null) {
60 |
61 | if (event.getAction() == MotionEvent.ACTION_UP) {
62 |
63 | boolean touchable = event.getX() > (getWidth() - getPaddingRight() - mClearDrawable.getIntrinsicWidth())
64 | && (event.getX() < ((getWidth() - getPaddingRight())));
65 | if (touchable) { //选中了“删除”按钮
66 |
67 | this.setText("");
68 | }
69 | }
70 | }
71 | return super.onTouchEvent(event);
72 | }
73 |
74 | /**
75 | * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
76 | */
77 | @Override
78 | public void onFocusChange(View v, boolean hasFocus) {
79 |
80 | if (hasFocus) {
81 |
82 | setClearIconVisible(getText().length() > 0);
83 | } else {
84 |
85 | setClearIconVisible(false);
86 | }
87 | }
88 |
89 | /**
90 | * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
91 | * @param visible
92 | */
93 | protected void setClearIconVisible(boolean visible) {
94 |
95 | Drawable right = visible ? mClearDrawable : null;
96 | setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
97 | }
98 |
99 | /**
100 | * 当输入框里面内容发生变化的时候回调的方法
101 | */
102 | @Override
103 | public void onTextChanged(CharSequence s, int start, int count, int after) {
104 | setClearIconVisible(s.length() > 0);
105 | }
106 |
107 | @Override
108 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
109 | }
110 |
111 | @Override
112 | public void afterTextChanged(Editable s) {
113 |
114 | }
115 | }
--------------------------------------------------------------------------------
/src/com/example/widget/SideBar.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import com.example.sortlistview.R;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Typeface;
9 | import android.graphics.drawable.ColorDrawable;
10 | import android.util.AttributeSet;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.widget.TextView;
14 |
15 | /**
16 | * 右侧首字母列表bar
17 | * @author Jack
18 | * @version 创建时间:2014-2-6 下午3:37:33
19 | */
20 | public class SideBar extends View {
21 |
22 | /** 触摸事件 */
23 | private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
24 | /** 26个字母 */
25 | public static String[] characters = { "A", "B", "C", "D", "E", "F", "G",
26 | "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
27 | "U", "V", "W", "X", "Y", "Z", "#" };
28 | private int ifSelected = -1; // 选中
29 | private Paint paint = new Paint();
30 | private TextView mTextDialog;
31 |
32 | public void setTextView(TextView mTextDialog) {
33 | this.mTextDialog = mTextDialog;
34 | }
35 |
36 | public SideBar(Context context, AttributeSet attrs, int defStyle) {
37 | super(context, attrs, defStyle);
38 | }
39 |
40 | public SideBar(Context context, AttributeSet attrs) {
41 | super(context, attrs);
42 | }
43 |
44 | public SideBar(Context context) {
45 | super(context);
46 | }
47 |
48 | /**
49 | * 重写这个方法
50 | */
51 | protected void onDraw(Canvas canvas) {
52 |
53 | super.onDraw(canvas);
54 | // 获取焦点改变背景颜色.
55 | int height = getHeight(); // 获取对应高度
56 | int width = getWidth(); // 获取对应宽度
57 | int singleHeight = height / characters.length; // 获取每一个字母的高度
58 |
59 | for (int i = 0; i < characters.length; i++) {
60 |
61 | // 设置颜色
62 | paint.setColor(Color.rgb(33, 65, 98));
63 | // 设置字体
64 | paint.setTypeface(Typeface.DEFAULT_BOLD);
65 | // 设置抗锯齿
66 | paint.setAntiAlias(true);
67 | // 设置字体大小
68 | paint.setTextSize(20);
69 | // 选中的状态
70 | if (i == ifSelected) {
71 |
72 | paint.setColor(Color.parseColor("#3399ff"));
73 | paint.setFakeBoldText(true);
74 | }
75 | // x坐标等于中间-字符串宽度的一半.
76 | float xPos = width / 2 - paint.measureText(characters[i]) / 2;
77 | float yPos = singleHeight * i + singleHeight;
78 | canvas.drawText(characters[i], xPos, yPos, paint);
79 | paint.reset();// 重置画笔
80 | }
81 | }
82 |
83 | @Override
84 | public boolean dispatchTouchEvent(MotionEvent event) {
85 |
86 | final int action = event.getAction();
87 | final float y = event.getY();// 点击y坐标
88 | final int oldSelected = ifSelected;
89 | final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
90 | final int selected = (int) (y / getHeight() * characters.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
91 |
92 | switch (action) {
93 |
94 | case MotionEvent.ACTION_UP:
95 |
96 | setBackgroundDrawable(new ColorDrawable(0x00000000));
97 | ifSelected = -1;//
98 | invalidate();
99 | if (mTextDialog != null) {
100 | mTextDialog.setVisibility(View.INVISIBLE);
101 | }
102 | break;
103 | default:
104 |
105 | setBackgroundResource(R.drawable.sidebar_background);
106 | if (oldSelected != selected) {
107 | if (selected >= 0 && selected < characters.length) {
108 | if (listener != null) {
109 | listener.onTouchingLetterChanged(characters[selected]);
110 | }
111 | if (mTextDialog != null) {
112 | mTextDialog.setText(characters[selected]);
113 | mTextDialog.setVisibility(View.VISIBLE);
114 | }
115 | ifSelected = selected;
116 | invalidate();
117 | }
118 | }
119 | break;
120 | }
121 | return true;
122 | }
123 |
124 | /**
125 | * 向外公开的方法
126 | * @param onTouchingLetterChangedListener
127 | */
128 | public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
129 |
130 | this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
131 | }
132 |
133 | /**
134 | * 触碰右侧列表时的回调接口
135 | */
136 | public interface OnTouchingLetterChangedListener {
137 | public void onTouchingLetterChanged(String s);
138 | }
139 | }
--------------------------------------------------------------------------------