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

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

快速索引7步曲:

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

* 2. 处理Touch事件.

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

* 4. 汉字转换成拼音.

* 5. 进行排序展示.

* 6. 进行分组.

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

1.A-Z索引的绘制

protected void onDraw(Canvas canvas) {

    for (int i = 0; i < LETTERS.length; i++) {
String text = LETTERS[i];
// 计算坐标
int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);
// 获取文本的高度
Rect bounds = new Rect();// 矩形
mPaint.getTextBounds(text, 0, text.length(), bounds);
int textHeight = bounds.height();
int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i * cellHeight); // 根据按下的字母, 设置画笔颜色
mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE); // 绘制文本A-Z
canvas.drawText(text, x, y, mPaint);
}
}

2 处理Touch事件

int touchIndex = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
int index = -1;
switch (MotionEventCompat.getActionMasked(event)) {
case MotionEvent.ACTION_DOWN:
// 获取当前触摸到的字母索引
index = (int) (event.getY() / cellHeight);
if(index >= 0 && index < LETTERS.length){
// 判断是否跟上一次触摸到的一样
if(index != touchIndex) {
if(listener != null){
listener.onLetterUpdate(LETTERS[index]);
}
Log.d(TAG, "onTouchEvent: " + LETTERS[index]); touchIndex = index;
}
}
break;
case MotionEvent.ACTION_MOVE:
index = (int) (event.getY() / cellHeight);
if(index >= 0 && index < LETTERS.length){
// 判断是否跟上一次触摸到的一样
if(index != touchIndex){ if(listener != null){
listener.onLetterUpdate(LETTERS[index]);
}
Log.d(TAG, "onTouchEvent: " + LETTERS[index]); touchIndex = index;
}
}
break;
case MotionEvent.ACTION_UP:
touchIndex = -1;
break; default:
break;
}
invalidate(); return true;
}

3.提供使用监听\回调

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

4.汉字转换成拼音

开源包:pingyin4j.jar

public static String getPinyin(String str) {

    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); StringBuilder sb = new StringBuilder(); char[] charArray = str.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
// 如果是空格, 跳过
if(Character.isWhitespace(c)){
continue;
}
if(c >= -127 && c < 128){
// 肯定不是汉字
sb.append(c);
}else {
String s = "";
try {
// 通过char得到拼音集合. 单 -> dan, shan
s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
sb.append(s);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
sb.append(s);
}
}
} return sb.toString();
}

显示字母

protected void showLetter(String letter) {
tv_center.setVisibility(View.VISIBLE);
tv_center.setText(letter); mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
tv_center.setVisibility(View.GONE);
}
}, 2000); }

5.进行排序展示

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

Adapter中:

static class ViewHolder {
TextView mIndex;
TextView mName; public static ViewHolder getHolder(View view) {
Object tag = view.getTag();
if(tag != null){
return (ViewHolder)tag;
}else {
ViewHolder viewHolder = new ViewHolder();
viewHolder.mIndex = (TextView) view.findViewById(R.id.tv_index);
viewHolder.mName = (TextView) view.findViewById(R.id.tv_name);
view.setTag(viewHolder);
return viewHolder;
}
}

6.进行分组

ViewHolder mViewHolder = ViewHolder.getHolder(view);

    Person p = persons.get(position);

    String str = null;
String currentLetter = p.getPinyin().charAt(0) + "";
// 根据上一个首字母,决定当前是否显示字母
if(position == 0){
str = currentLetter;
}else {
// 上一个人的拼音的首字母
String preLetter = persons.get(position - 1).getPinyin().charAt(0) + "";
if(!TextUtils.equals(preLetter, currentLetter)){
str = currentLetter;
}
} // 根据str是否为空,决定是否显示索引栏
mViewHolder.mIndex.setVisibility(str == null ? View.GONE : View.VISIBLE);
mViewHolder.mIndex.setText(currentLetter);
mViewHolder.mName.setText(p.getName()); return view;

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

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

快速索引 (对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. [LeetCode] Employee Importance 员工重要度

    You are given a data structure of employee information, which includes the employee's unique id, his ...

  2. vim 去除代码行号并正常缩进代码

    先命令模式下输入 :%s/[ \t]*\d\{1,4\}/ 即使用正则表达式替换   后命令模式下输入 gg 调到行首 v 进入可视化 G 调到行尾 = 所有代码正常缩进  

  3. [SCOI 2011]糖果

    Description 题库链接 给出 \(N\) 个节点,节点有正点权, \(K\) 个三元组 \((X,A,B)\) 来描述节点点权之间的关系. 如果 \(X=1\) , 表示 \(A\) 的点权 ...

  4. [HNOI 2003]消防局的设立

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

  5. [HAOI 2009]逆序对数列

    Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆 ...

  6. Evensgn 的债务

    问题 A: Evensgn 的债务 大致题意:a欠b5元,b欠c5元,那么最小债务总额为a欠c5元,给你关系,求最小债务总额! 不想说话...一句超级大水题,我居然没读懂!!差点想到网络流了...其实 ...

  7. bzoj 5287: [Hnoi2018]毒瘤

    Description Solution \(dfs\) 出一棵生成树之后,多出来的边就都是反祖边了 把反祖边两个端点都拿出来,就会得到最多 \(k=2*(m-n+1)\) 个关键点 除了关键点以外的 ...

  8. 数论:px+py 不能表示的最大数为pq-p-q的证明

    对于互质的两个数p,q,px+py 不能表示的最大数为pq-p-q. 证明: 先证:pq-p-q不能被px+py表示. 假设pq-p-q可以被px+py表示 那么 px+py=pq-p-q       ...

  9. 【CodeVs 6128 Lence的方块们】

    ·希望除了内部人员以外能有人通过这道题,因为这是大米饼第一次改编的题 ·我所见到的"本题原版"的题解也很少,搜索一下应该是: #include<stdio.h> #in ...

  10. hdu5558 后缀数组

    Alice's Classified Message Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K ...