快速索引 (对View的自定义)

快速索引应用场景: 微信好友列表, 联系人通讯录, 应用管理, 文件管理等。

快速索引7步曲:

*1. A-Z索引的绘制.

* 2. 处理Touch事件.

* 3. 提供使用监听\回调

* 4. 汉字转换成拼音.

* 5. 进行排序展示.

* 6. 进行分组.

* 7. 将自定义控件和ListView合体.

1.A-Z索引的绘制

  1. protected void onDraw(Canvas canvas) {
  2. for (int i = 0; i < LETTERS.length; i++) {
  3. String text = LETTERS[i];
  4. // 计算坐标
  5. int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);
  6. // 获取文本的高度
  7. Rect bounds = new Rect();// 矩形
  8. mPaint.getTextBounds(text, 0, text.length(), bounds);
  9. int textHeight = bounds.height();
  10. int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i * cellHeight);
  11. // 根据按下的字母, 设置画笔颜色
  12. mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE);
  13. // 绘制文本A-Z
  14. canvas.drawText(text, x, y, mPaint);
  15. }
  16. }

2 处理Touch事件

  1. int touchIndex = -1;
  2. @Override
  3. public boolean onTouchEvent(MotionEvent event) {
  4. int index = -1;
  5. switch (MotionEventCompat.getActionMasked(event)) {
  6. case MotionEvent.ACTION_DOWN:
  7. // 获取当前触摸到的字母索引
  8. index = (int) (event.getY() / cellHeight);
  9. if(index >= 0 && index < LETTERS.length){
  10. // 判断是否跟上一次触摸到的一样
  11. if(index != touchIndex) {
  12. if(listener != null){
  13. listener.onLetterUpdate(LETTERS[index]);
  14. }
  15. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
  16. touchIndex = index;
  17. }
  18. }
  19. break;
  20. case MotionEvent.ACTION_MOVE:
  21. index = (int) (event.getY() / cellHeight);
  22. if(index >= 0 && index < LETTERS.length){
  23. // 判断是否跟上一次触摸到的一样
  24. if(index != touchIndex){
  25. if(listener != null){
  26. listener.onLetterUpdate(LETTERS[index]);
  27. }
  28. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
  29. touchIndex = index;
  30. }
  31. }
  32. break;
  33. case MotionEvent.ACTION_UP:
  34. touchIndex = -1;
  35. break;
  36. default:
  37. break;
  38. }
  39. invalidate();
  40. return true;
  41. }

3.提供使用监听\回调

  1. QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar);
  2. // 设置监听
  3. bar.setListener(new OnLetterUpdateListener() {
  4. ......}

4.汉字转换成拼音

开源包:pingyin4j.jar

  1. public static String getPinyin(String str) {
  2. HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
  3. format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
  4. format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
  5. StringBuilder sb = new StringBuilder();
  6. char[] charArray = str.toCharArray();
  7. for (int i = 0; i < charArray.length; i++) {
  8. char c = charArray[i];
  9. // 如果是空格, 跳过
  10. if(Character.isWhitespace(c)){
  11. continue;
  12. }
  13. if(c >= -127 && c < 128){
  14. // 肯定不是汉字
  15. sb.append(c);
  16. }else {
  17. String s = "";
  18. try {
  19. // 通过char得到拼音集合. 单 -> dan, shan
  20. s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
  21. sb.append(s);
  22. } catch (BadHanyuPinyinOutputFormatCombination e) {
  23. e.printStackTrace();
  24. sb.append(s);
  25. }
  26. }
  27. }
  28. return sb.toString();
  29. }

显示字母

  1. protected void showLetter(String letter) {
  2. tv_center.setVisibility(View.VISIBLE);
  3. tv_center.setText(letter);
  4. mHandler.removeCallbacksAndMessages(null);
  5. mHandler.postDelayed(new Runnable() {
  6. @Override
  7. public void run() {
  8. tv_center.setVisibility(View.GONE);
  9. }
  10. }, 2000);
  11. }

5.进行排序展示

  1. private void fillAndSortData(ArrayList<Person> persons) {
  2. // 填充数据
  3. for (int i = 0; i < Cheeses.NAMES.length; i++) {
  4. String name = Cheeses.NAMES[i];
  5. persons.add(new Person(name));
  6. }
  7. // 进行排序
  8. Collections.sort(persons);
  9. }

Adapter中:

  1. static class ViewHolder {
  2. TextView mIndex;
  3. TextView mName;
  4. public static ViewHolder getHolder(View view) {
  5. Object tag = view.getTag();
  6. if(tag != null){
  7. return (ViewHolder)tag;
  8. }else {
  9. ViewHolder viewHolder = new ViewHolder();
  10. viewHolder.mIndex = (TextView) view.findViewById(R.id.tv_index);
  11. viewHolder.mName = (TextView) view.findViewById(R.id.tv_name);
  12. view.setTag(viewHolder);
  13. return viewHolder;
  14. }
  15. }

6.进行分组

  1. ViewHolder mViewHolder = ViewHolder.getHolder(view);
  2. Person p = persons.get(position);
  3. String str = null;
  4. String currentLetter = p.getPinyin().charAt(0) + "";
  5. // 根据上一个首字母,决定当前是否显示字母
  6. if(position == 0){
  7. str = currentLetter;
  8. }else {
  9. // 上一个人的拼音的首字母
  10. String preLetter = persons.get(position - 1).getPinyin().charAt(0) + "";
  11. if(!TextUtils.equals(preLetter, currentLetter)){
  12. str = currentLetter;
  13. }
  14. }
  15. // 根据str是否为空,决定是否显示索引栏
  16. mViewHolder.mIndex.setVisibility(str == null ? View.GONE : View.VISIBLE);
  17. mViewHolder.mIndex.setText(currentLetter);
  18. mViewHolder.mName.setText(p.getName());
  19. return view;

7.将自定义控件和ListView结合起来

  1. showLetter(letter);
  2. // 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引
  3. for (int i = 0; i < persons.size(); i++) {
  4. Person person = persons.get(i);
  5. String l = person.getPinyin().charAt(0) + "";
  6. if(TextUtils.equals(letter, l)){
  7. // 匹配成功
  8. mMainList.setSelection(i);
  9. break;
  10. }
  11. }

快速索引 (对View的自定义)的更多相关文章

  1. Android ListView A~Z快速索引(改进版)

    上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...

  2. 实现ListView A~Z快速索引

    ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...

  3. Android-自定义联系人快速索引

    效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...

  4. 8.快速索引、listview

    实现这样的效果 布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  5. Log4net快速索引参考

    官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...

  6. Dialog详解(包括进度条、PopupWindow、自定义view、自定义样式的对话框)

    Dialog详解(包括进度条.PopupWindow.自定义view.自定义样式的对话框)   Android中提供了多种对话框,在实际应用中我们可能会需要修改这些已有的对话框.本实例就是从实际出发, ...

  7. Android 快速索引(城市列表和联系人)

    最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...

  8. 通过圆形载入View了解自定义View

    这是自定义View的第一篇文章,通过制作简单的自定义View来了解自定义View的流程. 自定义View是Android学习和开发中必不可少的一部分.通过自定义View我们可以制作丰富绚丽的控件,自定 ...

  9. 【大盛】HTC one/M7 ROM 最新本地化OrDroid8.2.6 高级、快速设置 永久root 更多自定义 稳定 流畅

    了解更多:点击下载ROM和学习更多 ROM版本 HTC-one_OrDroid8.2.6 ROM作者 雪狼团队·大盛 http://weibo.com/DaShengdd Android版本 Andr ...

随机推荐

  1. sprintf格式化字符串带来的注入隐患

    原文链接:https://paper.seebug.org/386/ 摘要点关键知识点 <?php $input = addslashes("%1$' and 1=1#"); ...

  2. Redis常用命令--Hashes

    Hash是由键值对组成的map.Hashes的底层是通过字典实现的.一个哈希表里面可以有多个哈希表节点.而每个哈希节点就保存了字典中的一个键值对. 字典是一种用于保存键和值对的抽象数据结构.字典里的每 ...

  3. [HNOI2003]消防局的设立

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  4. [HNOI2011]数学作业

    题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M,要求计算 Concatenate (1 .. N) Mod M 的值,其中 Concatenat ...

  5. [UOJ] #217. 【UNR #1】奇怪的线段树

    题解见大佬博客 我的丑陋代码: #include<cstdio> #include<cstring> #include<cstdlib> inline int re ...

  6. ●UOJ 34 多项式乘法

    题链: http://uoj.ac/problem/34 题解: FFT入门题. (终于接触到迷一样的FFT了) 初学者在对复数和单位根有简单了解的基础上,可以直接看<再探快速傅里叶变换> ...

  7. ●POJ 1556 The Doors(简单计算几何+最短路)

    ●赘述题目 10*10的房间内,有竖着的一些墙(不超过18个).问从点(0,5)到(10,5)的最短路. 按照输入样例,输入的连续5个数,x,y1,y2,y3,y4,表示(x,0--y1),(x,y2 ...

  8. bzoj 3751: [NOIP2014]解方程

    Description 已知多项式方程: a0+a1x+a2x^2+...+an*x^n=0 求这个方程在[1,m]内的整数解(n和m均为正整数). 解题报告: 这题比较诡,看到高精度做不了,就要想到 ...

  9. Luogu1613 跑路

    题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟 ...

  10. hdu 5538(水)

    Input The first line contains an integer T indicating the total number of test cases. First line of ...