1.  
  1. package com.lixu.letterlistview;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import org.apache.http.NameValuePair;
  6. import org.apache.http.message.BasicNameValuePair;
  7. import com.lixu.letterlistview.letter.LetterBaseListAdapter;
  8. import com.lixu.letterlistview.letter.LetterListView;
  9. import com.lixu.lianxirenlist.R;
  10. import android.app.Activity;
  11. import android.content.ContentResolver;
  12. import android.database.Cursor;
  13. import android.graphics.Color;
  14. import android.net.Uri;
  15. import android.os.Bundle;
  16. import android.view.Gravity;
  17. import android.view.View;
  18. import android.view.ViewGroup;
  19. import android.widget.TextView;
  20.  
  21. public class MainActivity extends Activity {
  22. private ArrayList<String> dataArray;
  23.  
  24. @Override
  25. protected void onCreate(Bundle savedInstanceState) {
  26. super.onCreate(savedInstanceState);
  27. setContentView(R.layout.activity_main);
  28. // 通过获取手机通讯录的姓名
  29. dataArray = new ArrayList<String>();
  30.  
  31. Uri uri = Uri.parse("content://com.android.contacts/contacts");
  32. ContentResolver resolver = this.getContentResolver();
  33. // 给query传递一个SORT_KEY_PRIMARY,让ContentResolver将获得的数据按照联系人名字首字母排序
  34. Cursor cursor = resolver.query(uri, null, null, null,
  35. android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY);
  36. while (cursor.moveToNext())
  37.  
  38. {
  39. // 联系人的id
  40. String id = cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
  41. // 将联系人按姓名首字母分组
  42. String sort_key_primary = cursor
  43. .getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY));
  44. // 获取联系人的名字
  45. String name = cursor
  46. .getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME));
  47. dataArray.add(name);
  48. }
  49.  
  50. LetterListView letterListView = (LetterListView) findViewById(R.id.letterListView);
  51. letterListView.setAdapter(new TestAdapter());
  52.  
  53. }
  54.  
  55. /**
  56. * 这里 使用一个简单的 NameValuePair 对象,做为测试
  57. *
  58. * @Title:
  59. * @Description:
  60. * @Author:Justlcw
  61. * @Since:2014-5-13
  62. * @Version:
  63. */
  64. class TestAdapter extends LetterBaseListAdapter<NameValuePair> {
  65. /** 字母对应的key,因为字母是要插入到列表中的,为了区别,所有字母的item都使用同一的key. **/
  66. private static final String LETTER_KEY = "letter";
  67.  
  68. public TestAdapter() {
  69. super();
  70.  
  71. List<NameValuePair> dataList = new ArrayList<NameValuePair>();
  72. for (int i = 0; i < dataArray.size(); i++) {
  73. NameValuePair pair = new BasicNameValuePair(String.valueOf(i), dataArray.get(i));
  74. dataList.add(pair);
  75. }
  76. setContainerList(dataList);
  77. }
  78.  
  79. @Override
  80. public Object getItem(int position) {
  81. return list.get(position);
  82. }
  83.  
  84. @Override
  85. public long getItemId(int position) {
  86. return position;
  87. }
  88.  
  89. @Override
  90. public String getItemString(NameValuePair t) {
  91. return t.getValue();
  92. }
  93.  
  94. @Override
  95. public NameValuePair create(char letter) {
  96. return new BasicNameValuePair(LETTER_KEY, String.valueOf(letter));
  97. }
  98.  
  99. @Override
  100. public boolean isLetter(NameValuePair t) {
  101. // 判断是不是字母行,通过key比较,这里是NameValuePair对象,其他对象,就由你自己决定怎么判断了.
  102. return t.getName().equals(LETTER_KEY);
  103. }
  104.  
  105. @Override
  106. public View getLetterView(int position, View convertView, ViewGroup parent) {
  107. // 这里是字母的item界面设置.
  108. if (convertView == null) {
  109. convertView = new TextView(MainActivity.this);
  110. ((TextView) convertView).setGravity(Gravity.CENTER_VERTICAL);
  111. convertView.setBackgroundColor(getResources().getColor(android.R.color.white));
  112. }
  113. ((TextView) convertView).setText(list.get(position).getValue());
  114. ((TextView) convertView).setBackgroundColor(Color.GREEN);
  115. ((TextView) convertView).setTextSize(25);
  116. return convertView;
  117. }
  118.  
  119. @Override
  120. public View getContainerView(int position, View convertView, ViewGroup parent) {
  121. // 这里是其他正常数据的item界面设置.
  122. if (convertView == null) {
  123. convertView = new TextView(MainActivity.this);
  124. ((TextView) convertView).setGravity(Gravity.CENTER_VERTICAL);
  125. }
  126. ((TextView) convertView).setText(list.get(position).getValue());
  127. ((TextView) convertView).setBackgroundColor(Color.YELLOW);
  128. ((TextView) convertView).setTextSize(20);
  129.  
  130. return convertView;
  131. }
  132. }
  133. }
  1. package com.lixu.letterlistview.letter;
  2.  
  3. import android.widget.BaseAdapter;
  4.  
  5. /**
  6. * 带有侧边字母列表的listView适配器
  7. *
  8. *@Title:
  9. *@Description:
  10. *@Author:Justlcw
  11. *@Since:2014-5-8
  12. *@Version:
  13. */
  14. public abstract class LetterBaseAdapter extends BaseAdapter
  15. {
  16. /** 字母表头部 **/
  17. protected static final char HEADER = '+';
  18. /** 字母表尾部 **/
  19. protected static final char FOOTER = '#';
  20.  
  21. /**
  22. * 是否需要隐藏没有匹配到的字母
  23. *
  24. * @return true 隐藏, false 不隐藏
  25. * @Description:
  26. * @Author Justlcw
  27. * @Date 2014-5-8
  28. */
  29. public abstract boolean hideLetterNotMatch();
  30.  
  31. /**
  32. * 获取字母对应的位置
  33. *
  34. * @return position
  35. * @Description:
  36. * @Author Justlcw
  37. * @Date 2014-5-8
  38. */
  39. public abstract int getIndex(char letter);
  40. }
  1. package com.lixu.letterlistview.letter;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import android.text.TextUtils;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.view.ViewGroup;
  11.  
  12. /**
  13. * 通用带有字母列表的泛型对象adapter
  14. *
  15. * @Title:
  16. * @Description:
  17. * @Author:Justlcw
  18. * @Since:2014-5-9
  19. * @Version:
  20. */
  21. public abstract class LetterBaseListAdapter<T> extends LetterBaseAdapter {
  22. /** log tag. **/
  23. private static final String TAG = "LetterBaseListAdapter";
  24.  
  25. /** 默认错误头部字母. **/
  26. private static final char ERROR_LETTER = ' ';
  27.  
  28. /** view type的类型总数 **/
  29. private static final int TYPE_COUNT = 2;
  30. /** 字母类型 **/
  31. private static final int TYPE_LETTER = 0;
  32. /** 实体类型 **/
  33. private static final int TYPE_CONTAINER = 1;
  34.  
  35. /** 添加字母之后的list **/
  36. protected final List<T> list;
  37. /** 字母头位置标示map **/
  38. private final Map<Character, Integer> letterMap;
  39.  
  40. /**
  41. * 构造方法
  42. */
  43. public LetterBaseListAdapter() {
  44. list = new ArrayList<T>();
  45. letterMap = new HashMap<Character, Integer>();
  46. }
  47.  
  48. /**
  49. * 构造方法
  50. *
  51. * @param dataArray
  52. * 内容数组
  53. */
  54. public LetterBaseListAdapter(T[] dataArray) {
  55. this();
  56. setContainerList(dataArray);
  57. }
  58.  
  59. /**
  60. * 构造方法
  61. *
  62. * @param dataList
  63. * 内容列表
  64. */
  65. public LetterBaseListAdapter(List<T> dataList) {
  66. this();
  67. setContainerList(dataList);
  68. }
  69.  
  70. /**
  71. * 设置主体内容
  72. *
  73. * @param dataArray
  74. * 实体数组
  75. * @Description:
  76. * @Author Justlcw
  77. * @Date 2014-5-9
  78. */
  79. protected final void setContainerList(T[] dataArray) {
  80. if (!list.isEmpty()) {
  81. list.clear();
  82. }
  83. if (!letterMap.isEmpty()) {
  84. letterMap.clear();
  85. }
  86.  
  87. char letter = ERROR_LETTER;
  88. int index = 0;
  89. for (int i = 0; i < dataArray.length; i++) {
  90. T t = dataArray[i];
  91.  
  92. char l = getHeaderLetter(t);
  93.  
  94. if (letter != l && l != ERROR_LETTER) {
  95. // 如果发现这个字母没有添加过,更新一下标示
  96. letter = l;
  97. // 创建一个T类型的字母头放进去
  98. T tl = create(letter);
  99. if (tl != null) {
  100. // 如果创建成功,则插入到列表中
  101. list.add(tl);
  102. }
  103. // 存放最新字母对应的位置
  104. letterMap.put(letter, index);
  105. index++;
  106. }
  107. // 添加原本的填充实体项
  108. list.add(t);
  109. index++;
  110. }
  111. }
  112.  
  113. /**
  114. * 设置主体内容.
  115. *
  116. * @param dataList
  117. * 实体列表
  118. * @Description:
  119. * @Author Justlcw
  120. * @Date 2014-5-9
  121. */
  122. protected final void setContainerList(List<T> dataList) {
  123. if (!list.isEmpty()) {
  124. list.clear();
  125. }
  126. if (!letterMap.isEmpty()) {
  127. letterMap.clear();
  128. }
  129.  
  130. char letter = ' ';
  131. int index = 0;
  132. for (int i = 0; i < dataList.size(); i++) {
  133. T t = dataList.get(i);
  134.  
  135. char l = getHeaderLetter(t);
  136.  
  137. if (letter != l && l != ERROR_LETTER) {
  138. // 如果发现这个字母没有添加过,更新一下标示
  139. letter = l;
  140. // 创建一个T类型的字母头放进去
  141. T tl = create(letter);
  142. if (tl != null) {
  143. // 如果创建成功,则插入到列表中
  144. list.add(tl);
  145. }
  146. // 存放最新字母对应的位置
  147. letterMap.put(letter, index);
  148. index++;
  149. }
  150. // 添加原本的填充实体项
  151. list.add(t);
  152. index++;
  153. }
  154. }
  155.  
  156. /**
  157. * @param t
  158. * <实体item对象>
  159. *
  160. * @return <实体item对象> 首字母, 获取失败返回 {@link #ERROR_LETTER}
  161. * @Description:
  162. * @Author Justlcw
  163. * @Date 2014-5-12
  164. */
  165. private char getHeaderLetter(T t) {
  166. // 获取item对应的字符串
  167. String str = getItemString(t);
  168. // 如果为空,跳出继续
  169. if (TextUtils.isEmpty(str)) {
  170. Log.e(TAG, "item string empty in " + t.toString());
  171. return ERROR_LETTER;
  172. }
  173. char l;
  174. // 获取第一个字母
  175. char firstChar = str.charAt(0);
  176. if (firstChar == HEADER || firstChar == FOOTER || LetterUtil.isLetter(firstChar)) {
  177. l = firstChar;// 如果是头,尾,字母,直接赋值
  178. } else {
  179. String[] letterArray = LetterUtil.getFirstPinyin(firstChar);
  180. // 如果是汉字,取拼音首字母
  181. if (letterArray != null && letterArray.length > 0) {
  182. l = letterArray[0].charAt(0);
  183. } else {
  184. // 如果汉字转拼音失败了,跳过
  185. Log.e(TAG, firstChar + " turn to letter fail, " + t.toString());
  186. return ERROR_LETTER;
  187. }
  188. }
  189.  
  190. // 如果是小写字母,转换为大写字母
  191. if (l >= 'a') {
  192. l = (char) (l - 32);
  193. }
  194. return l;
  195. }
  196.  
  197. @Override
  198. public final int getCount() {
  199. return list.size();
  200. }
  201.  
  202. @Override
  203. public final View getView(int position, View convertView, ViewGroup parent) {
  204. if (getItemViewType(position) == TYPE_LETTER) {
  205. return getLetterView(position, convertView, parent);
  206. }
  207. return getContainerView(position, convertView, parent);
  208. }
  209.  
  210. @Override
  211. public final int getItemViewType(int position) {
  212. if (isLetter(list.get(position))) {
  213. return TYPE_LETTER;
  214. }
  215. return TYPE_CONTAINER;
  216. }
  217.  
  218. @Override
  219. public final int getViewTypeCount() {
  220. return TYPE_COUNT;
  221. }
  222.  
  223. @Override
  224. public boolean hideLetterNotMatch() {
  225. return false;
  226. }
  227.  
  228. @Override
  229. public final int getIndex(char letter) {
  230. Integer index = letterMap.get(letter);
  231. if (index == null) {
  232. return -1;
  233. }
  234. return index;
  235. }
  236.  
  237. /**
  238. * @param T
  239. * <实体item对象>
  240. *
  241. * @return <实体item对象>对应的String,用来获取<拼音首字母>
  242. * @Description:
  243. * @Author Justlcw
  244. * @Date 2014-5-9
  245. */
  246. public abstract String getItemString(T t);
  247.  
  248. /**
  249. * @param letter
  250. * <字母>
  251. *
  252. * @return 根据<字母>创建一个<实体item对象>,用来显示<字母item>
  253. * @Description:
  254. * @Author Justlcw
  255. * @Date 2014-5-9
  256. */
  257. public abstract T create(char letter);
  258.  
  259. /**
  260. * @param t
  261. * <实体item对象>
  262. *
  263. * @return 根据<实体item对象>,判断是否是<字母item>
  264. * @Description:
  265. * @Author Justlcw
  266. * @Date 2014-5-9
  267. */
  268. public abstract boolean isLetter(T t);
  269.  
  270. /**
  271. * 返回 <字母item>界面,其他的同
  272. * <P>
  273. * {@link #getView(int, View, ViewGroup)}
  274. *
  275. * @Description:
  276. * @Author Justlcw
  277. * @Date 2014-5-9
  278. */
  279. public abstract View getLetterView(int position, View convertView, ViewGroup parent);
  280.  
  281. /**
  282. * 返回<实体item>界面,其他的同
  283. * <P>
  284. * {@link #getView(int, View, ViewGroup)}
  285. *
  286. * @Description:
  287. * @Author Justlcw
  288. * @Date 2014-5-9
  289. */
  290. public abstract View getContainerView(int position, View convertView, ViewGroup parent);
  291. }
  1. package com.lixu.letterlistview.letter;
  2.  
  3. import java.lang.ref.SoftReference;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6.  
  7. import com.lixu.lianxirenlist.R;
  8. import android.content.Context;
  9. import android.os.Handler;
  10. import android.os.Message;
  11. import android.util.AttributeSet;
  12. import android.view.Gravity;
  13. import android.view.LayoutInflater;
  14. import android.view.MotionEvent;
  15. import android.view.View;
  16. import android.view.ViewGroup;
  17. import android.widget.AbsListView;
  18. import android.widget.BaseAdapter;
  19. import android.widget.FrameLayout;
  20. import android.widget.ListView;
  21. import android.widget.TextView;
  22. import android.widget.AdapterView.OnItemClickListener;
  23.  
  24. /**
  25. * 带有字母列表的listView
  26. *
  27. * @Title:
  28. * @Description:
  29. * @Author:Justlcw
  30. * @Since:2014-5-7
  31. * @Version:
  32. */
  33. public class LetterListView extends FrameLayout {
  34. /** 隐藏字母消息 **/
  35. private final int MSG_HIDE_LETTER = 0x0;
  36.  
  37. /** 字母列表的宽度 **/
  38. private final int LETTER_LIST_VIEW_WIDTH = 50;// TODO 这里宽度写死了,按着一定的比例比较好
  39.  
  40. /** 内容列表 **/
  41. private ListView mListView;
  42. /** 内容列表适配器 **/
  43. private LetterBaseAdapter mAdapter;
  44.  
  45. /** 字母列表 **/
  46. private ListView mLetterListView;
  47. private LetterAdapter mLetterAdapter;
  48.  
  49. private TextView mLetterTextView;
  50.  
  51. /** 字母消息Handler **/
  52. private Handler mLetterhandler;
  53.  
  54. /**
  55. * 构造方法
  56. *
  57. * @param context
  58. */
  59. public LetterListView(Context context) {
  60. super(context);
  61. initListView(context);
  62. }
  63.  
  64. /**
  65. * 构造方法
  66. *
  67. * @param context
  68. * @param attrs
  69. */
  70. public LetterListView(Context context, AttributeSet attrs) {
  71. super(context, attrs);
  72. initListView(context);
  73. }
  74.  
  75. /**
  76. * 初始化 内容列表 字母列表
  77. *
  78. * @Description:
  79. * @Author Justlcw
  80. * @Date 2014-5-7
  81. */
  82. private void initListView(Context context) {
  83. LayoutInflater inflater = LayoutInflater.from(getContext());
  84. // TODO 这里添加内容列表,可以在这里对ListView进行一些你想要的设置
  85. mListView = (ListView) inflater.inflate(R.layout.letter_list_container, null, false);
  86. LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
  87. addView(mListView, lp);
  88.  
  89. // TODO 这里添加字母列表,可以在这里对ListView进行一些你想要的设置
  90. mLetterListView = (ListView) inflater.inflate(R.layout.letter_list_letter, null, false);
  91. mLetterListView.setOnTouchListener(mLetterOnTouchListener);
  92. LayoutParams letterListLp = new LayoutParams(LETTER_LIST_VIEW_WIDTH, LayoutParams.MATCH_PARENT, Gravity.RIGHT);
  93. addView(mLetterListView, letterListLp);
  94.  
  95. // TODO 这里对显示的字母进行设置
  96. mLetterTextView = (TextView) inflater.inflate(R.layout.letter_list_position, null, false);
  97. LayoutParams letterLp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER);
  98. addView(mLetterTextView, letterLp);
  99. mLetterTextView.setVisibility(View.INVISIBLE);
  100.  
  101. // 初始化letter消息发送者
  102. mLetterhandler = new LetterHandler(this);
  103. }
  104.  
  105. /**
  106. * 设置内容列表适配器
  107. *
  108. * @param adapter
  109. * {@link LetterBaseAdapter}
  110. * @Description:
  111. * @Author Justlcw
  112. * @Date 2014-5-7
  113. */
  114. public void setAdapter(LetterBaseAdapter adapter) {
  115. if (adapter != null) {
  116. mAdapter = adapter;
  117. mListView.setAdapter(mAdapter);
  118. }
  119. }
  120.  
  121. /**
  122. * {@link AbsListView#setOnItemClickListener(OnItemClickListener)}
  123. *
  124. * @Description:
  125. * @Author Justlcw
  126. * @Date 2014-5-14
  127. */
  128. public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
  129. mListView.setOnItemClickListener(onItemClickListener);
  130. }
  131.  
  132. @Override
  133. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  134. super.onSizeChanged(w, h, oldw, oldh);
  135.  
  136. mLetterAdapter = new LetterAdapter(h - getPaddingTop() - getPaddingBottom());
  137. mLetterListView.setAdapter(mLetterAdapter);
  138. }
  139.  
  140. /**
  141. * 显示字母
  142. *
  143. * @Description:
  144. * @Author Justlcw
  145. * @Date 2014-5-8
  146. */
  147. private void showLetter(String letter) {
  148. if (mLetterTextView.getVisibility() != View.VISIBLE) {
  149. mLetterTextView.setVisibility(View.VISIBLE);
  150. mLetterListView.setBackgroundResource(android.R.color.darker_gray);
  151. }
  152. mLetterTextView.setText(letter);
  153.  
  154. mLetterhandler.removeMessages(MSG_HIDE_LETTER);
  155. mLetterhandler.sendEmptyMessageDelayed(MSG_HIDE_LETTER, 500);
  156. }
  157.  
  158. /**
  159. * 处理消息 {@link LetterHandler#handleMessage(Message)}
  160. *
  161. * @param msg
  162. * 消息
  163. * @Description:
  164. * @Author Justlcw
  165. * @Date 2014-5-8
  166. */
  167. private void handleLetterMessage(Message msg) {
  168. mLetterTextView.setVisibility(View.INVISIBLE);
  169. mLetterListView.setBackgroundResource(android.R.color.white);
  170. }
  171.  
  172. /** 字母栏touch事件 **/
  173. private View.OnTouchListener mLetterOnTouchListener = new View.OnTouchListener() {
  174. @Override
  175. public boolean onTouch(View v, MotionEvent event) {
  176. int height = (int) event.getY() - v.getTop();
  177.  
  178. int position = mLetterAdapter.getTouchPoistion(height);
  179. if (position >= 0) {
  180. char letter = (Character) mLetterAdapter.getItem(position);
  181. // 显示字母
  182. showLetter(String.valueOf(letter));
  183.  
  184. // 显示到字母对应的位置
  185. int select = mAdapter.getIndex(letter);
  186. if (select >= 0) {
  187. mListView.setSelection(select);
  188. }
  189. return true;
  190. }
  191. return false;
  192. }
  193. };
  194.  
  195. /**
  196. * 字母列表设配器
  197. *
  198. * @Title:
  199. * @Description:
  200. * @Author:Justlcw
  201. * @Since:2014-5-7
  202. * @Version:
  203. */
  204. private class LetterAdapter extends BaseAdapter {
  205. /** 字母表 **/
  206. private static final String LETTER_STR = "+ABCDEFGHIJKLMNOPQRSTUVWXYZ#";
  207. /** 最终显示的字母array **/
  208. private char[] letterArray;
  209. /** 每个字母的高度 **/
  210. private int itemHeight;
  211.  
  212. /**
  213. * 构造方法
  214. *
  215. * @param height
  216. * view height
  217. */
  218. public LetterAdapter(int height) {
  219. if (mAdapter.hideLetterNotMatch()) {
  220. List<Character> list = new ArrayList<Character>();
  221. char[] allArray = LETTER_STR.toCharArray();
  222. for (int i = 0; i < allArray.length; i++) {
  223. char letter = allArray[i];
  224. int position = mAdapter.getIndex(letter);
  225. if (position >= 0) {
  226. list.add(letter);
  227. }
  228. }
  229. letterArray = new char[list.size()];
  230. for (int i = 0; i < list.size(); i++) {
  231. letterArray[i] = list.get(i);
  232. }
  233. list.clear();
  234. list = null;
  235. } else {
  236. letterArray = LETTER_STR.toCharArray();
  237. }
  238. itemHeight = height / letterArray.length;
  239. }
  240.  
  241. @Override
  242. public int getCount() {
  243. return letterArray.length;
  244. }
  245.  
  246. @Override
  247. public Object getItem(int position) {
  248. return letterArray[position];
  249. }
  250.  
  251. @Override
  252. public long getItemId(int position) {
  253. return position;
  254. }
  255.  
  256. @Override
  257. public View getView(int position, View convertView, ViewGroup parent) {
  258. if (convertView == null) {
  259. convertView = new TextView(getContext());
  260. ((TextView) convertView).setTextColor(getResources().getColor(android.R.color.black));
  261. ((TextView) convertView).setGravity(Gravity.CENTER);
  262. AbsListView.LayoutParams lp = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
  263. itemHeight);
  264. convertView.setLayoutParams(lp);
  265. }
  266. ((TextView) convertView).setText(String.valueOf(letterArray[position]));
  267.  
  268. return convertView;
  269. }
  270.  
  271. /**
  272. * 获取touch的位置
  273. *
  274. * @return position
  275. * @Description:
  276. * @Author Justlcw
  277. * @Date 2014-5-8
  278. */
  279. public int getTouchPoistion(int touchHeight) {
  280. int position = touchHeight / itemHeight;
  281. if (position >= 0 && position < getCount()) {
  282. return position;
  283. }
  284. return -1;
  285. }
  286. }
  287.  
  288. /**
  289. * 处理字母显示的handler.
  290. *
  291. * @Title:
  292. * @Description:
  293. * @Author:Justlcw
  294. * @Since:2014-5-8
  295. * @Version:
  296. */
  297. private static class LetterHandler extends Handler {
  298. /** 弱引用 {@link LetterListView} **/
  299. private SoftReference<LetterListView> srLetterListView;
  300.  
  301. /**
  302. * 构造方法
  303. *
  304. * @param letterListView
  305. * {@link LetterListView}
  306. */
  307. public LetterHandler(LetterListView letterListView) {
  308. srLetterListView = new SoftReference<LetterListView>(letterListView);
  309. }
  310.  
  311. @Override
  312. public void handleMessage(Message msg) {
  313. LetterListView letterListView = srLetterListView.get();
  314. // 如果view没有被销毁掉,交给view处理这个消息
  315. if (letterListView != null) {
  316. letterListView.handleLetterMessage(msg);
  317. }
  318. }
  319. }
  320. }
  1. package com.lixu.letterlistview.letter;
  2.  
  3. import net.sourceforge.pinyin4j.PinyinHelper;
  4.  
  5. /**
  6. * 字母工具类
  7. *@Title:
  8. *@Description:
  9. *@Author:Justlcw
  10. *@Since:2014-5-8
  11. *@Version:
  12. */
  13. public class LetterUtil
  14. {
  15. /**
  16. * @param chinese 一个汉字
  17. * @return 拼音首字母
  18. * @Description:
  19. * @Author Justlcw
  20. * @Date 2014-5-8
  21. */
  22. public static String[] getFirstPinyin(char chinese)
  23. {
  24. return PinyinHelper.toHanyuPinyinStringArray(chinese);
  25. }
  26.  
  27. /**
  28. * 是否是字母
  29. *
  30. * @return true 字母,false 非字母
  31. * @Description:
  32. * @Author Justlcw
  33. * @Date 2014-5-8
  34. */
  35. public static boolean isLetter(char c)
  36. {
  37. return (c >= 65 && c <= 90) || (c >= 97 && c <= 112);
  38. }
  39. }

xml文件:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5.  
  6. <com.lixu.letterlistview.letter.LetterListView
  7. android:id="@+id/letterListView"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent" >
  10. </com.lixu.letterlistview.letter.LetterListView>
  11.  
  12. </RelativeLayout>
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <ListView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:cacheColorHint="@android:color/transparent"
  6. android:divider="@android:color/transparent"
  7. android:dividerHeight="0dp"
  8. android:scrollbars="none" />
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <ListView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#f44336"
  6. android:cacheColorHint="@android:color/transparent"
  7. android:divider="@android:color/transparent"
  8. android:dividerHeight="0dp"
  9. android:scrollbars="none" />
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <TextView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"
  5. android:background="#f44336"
  6. android:gravity="center"
  7. android:maxWidth="70dip"
  8. android:minWidth="70dip"
  9. android:padding="10dip"
  10. android:textColor="@android:color/black"
  11. android:textSize="50sp" />

运行效果图:

联系人的侧边字母索引ListView 将手机通讯录姓名通过首字母排序。的更多相关文章

  1. C# 汉字获取拼音首字母,给数据库中的姓名添加首字母

    本方案采用微软官方语言包 (下载链接: https://pan.baidu.com/s/10I1bhTdFr4-q_xKVHuEzMA 提取码: p3nk ChnCharInfo.dll 用于获取首字 ...

  2. 运用正则+replace+substring将一段英语的字母大写 angurlar运用自定义指令filter完成首字母大写

    复习下js基础并运用正则+replace+substring将一段英语的字母大写 <!DOCTYPE html><html> <head> <meta cha ...

  3. php实现姓名按首字母排序的类与方法

    php将名字按首字母进行排序 <?php public function getFirstChar($s){ $s0 = mb_substr($s,0,3); //获取名字的姓 $s = ico ...

  4. java通讯录获取汉字首字母

    1.本文只是使用了pinyin4J的主要功能,还有更多更好耍的功能,大家可以去研究官网文档.哈哈 2.pinyin4j的官方下载地址:https://sourceforge.net/projects/ ...

  5. HBuilder+eclipse开发:使用ajax异步传值生成首字母索引

    使用ajax异步传值生成首字母索引大致有以下几个步骤: 1.服务器端使用servlet提取出数据库里的数据; 2.使用首字母工具类对数据进处理得到首字母; 3.再将首字母和数据一一对应存入json数组 ...

  6. 【Solr】 solr对拼音搜索和拼音首字母搜索的支持

    问:对于拼音和拼音首字母的支持,当你在搜商品的时候,如果想输入拼音和拼音首字母就给出商品的信息,怎么办呢? 实现方式有2种,但是他们其实是对应的.  用lucene实现 1.建索引, 多建一个索引字段 ...

  7. JS获取中文拼音首字母,并通过拼音首字母高速查找页面内的中文内容

    实现效果: 图一: 图二: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGVzdGNzX2Ru/font/5a6L5L2T/fontsize/400/f ...

  8. Elasticsearch高级搜索排序( 中文+拼音+首字母+简繁转换+特殊符号过滤)

    一.先摆需求: 1.中文搜索.英文搜索.中英混搜   如:"南京东路","cafe 南京东路店" 2.全拼搜索.首字母搜索.中文+全拼.中文+首字母混搜   如 ...

  9. C# 汉字转拼音 使用微软的Visual Studio International Pack 类库提取汉字拼音首字母

    代码参考该文http://www.cnblogs.com/yazdao/archive/2011/06/04/2072488.html VS2015版本 1.使用Nuget 安装 "Simp ...

随机推荐

  1. jQuery Jcrop API参数说明(中文版)(转)(图片剪切)

    Jcrop是一个jQuery图片裁剪插件,它能为你的WEB应用程序快速简单地提供图片裁剪的功能.特点如下: 对所有图片均unobtrusively(无侵入的,保持DOM简洁) 支持宽高比例锁定 支持 ...

  2. show slave status

    Slave_IO_State: Waiting for master to send event                   Master_Host: 10.1.1.1             ...

  3. linux下,一些关于动态库的问题:

    程序运行是加载动态库的几种方法: 第一种,通过ldconfig命令    ldconfig是一个动态链接库管理命令,为了让动态链接库为系统所共享,还需运行动态链接库的管理命令它,ldconfig命令通 ...

  4. iOS 的 Safari 文件上传功能详解

    iOS 6 给 Safari 浏览器带来的另外一个功能是文件上传,终于 Safari 终于支持 input 输入框的文件类型了,并且还支持 HTML媒体捕获(HTML Media Capture). ...

  5. Kafka的配置文件详细描述

    在kafka/config/目录下面有3个配置文件: producer.properties consumer.properties server.properties (1).producer.pr ...

  6. hiho_1068_RMQ_st算法

    题目 给出一数组A,编号从1到n,然后进行q次查询,每次查询给出一个边界[beg, end],要求给出数组A中范围[beg, end]之内的最小值. 题目链接: RMQ_ST 分析 区间问题使用线段树 ...

  7. ulua slua 下载地址

    ulua http://www.yanyulin.info/pages/2015/01/27193946190814.html   http://www.manew.com/blog-27966-25 ...

  8. 【转】Android应用开发之PNG、IconFont、SVG图标资源优化详解

    1 背景 最近因为一些个人私事导致好久没写博客了,多事之年总算要过去了,突然没了动力,所以赶紧先拿个最近项目中重构的一个小知识点充下数,老题重谈. 在我们App开发中大家可能都会有过如下痛疾(程序员和 ...

  9. 各种U启网启什么的都是浮云

    对于支持BIOS的电脑,优盘启动,网络启动的各种方案感觉都是浮云,从硬盘启动PE进行维护才是最可靠的.不点在开发wee的过程中给了我们很多维护的灵感,不用费劲地折腾fbinst/U+/量产/PXE/I ...

  10. libCEF总结02字符串

    libCEF 的 CefString.cef_string_t 在 Windows 下均表示一个 16 位的 Unicode 字符串,它们的使用请参考下面的代码 {//wchar_t* ==> ...