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

快速索引 (对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;
                }
            }
时间: 2024-08-02 11:18:05

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

Android手机联系人快速索引(手机通讯录)_Android

最近需要实现一个手机通讯录的快速索引功能.根据姓名首字母快速索引功能.下面是一个手机联系人快速索引的效果,总体来说代码不算难,拼音转换的地方略有复杂.下面上源码:源码中有注释. 下面是效果图: MainActivity: import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.app.Activity; import android.os.Bundle; imp

android自定义view和自定义layout

问题描述 android自定义view和自定义layout 我自定义了一个view,实现一个图片的移动,然后我想在view添加一个按钮,网上说是要建一个layout,然后再add.求教具体方法啊,能不能不用layout直接用view添加按钮. 解决方案 类似如下 LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); Lin

【Spark Summit East 2017】大数据应用的工程快速索引(深度挖掘)

本讲义出自Daniel Lemire在Spark Summit East 2017上的演讲,主要介绍了对了应对高性能编程的挑战,分享了Daniel Lemire及团队在侧重于压缩位图索引设计快速索引时吸取的经验教训.

可支持快速搜索筛选的Android自定义选择控件

Android 自定义支持快速搜索筛选的选择控件使用方法,具体如下 项目中遇到选择控件选项过多,需要快速查找匹配的情况. 做了简单的Demo,效果图如下: 源码地址:https://github.com/whieenz/SearchSelect 这个控件是由Dialog+SearchView+ListView实现的.Dialog用来承载选择控件,SearchView实现输入,ListView展示结果.设计概要图如下: 一.自定义Dialog Dialog布局文件 <?xml version=&quo

Android自定义View之自定义评价打分控件RatingBar实现自定义星星大小和间距_Android

在Android开发中,我们经常会用到对商家或者商品的评价,运用星星进行打分.然而在Android系统中自带的打分控件,RatingBar特别不好用,间距和大小无法改变.所以,我就自定义了一个特别好用的打分控件.在项目中可以直接使用,特别简单.下面直接上图: 效果图 实现原理 其实就是自定义View继承LinearLayout ,然后里面动态加了五个ImageView. 实现代码,有详细的注释 在attrs中声明的可以在xml中设置的变量 <declare-styleable name="

快速索引的几种技巧

你可以采用两种不同的方式将内容加到你的网站中:一种是升级现有的网页,另一种是在全新的URL中增加内容.当然,新的内容应该在搜索引擎索引的过程中会被找到,你可以采用许多措施来帮助搜索引擎更快地对新的内容关注或是新的URL.与SEO中许多新词汇一样,一个网页引起搜索引擎的关注就是代码或是获得链接.由于关于链接的对话很多,质量对数量的争论现在比任何时候都重要了. 但是,质量并不是指引导到你网站的http://www.aliyun.com/zixun/aggregation/8882.html">

网站建立快速索引的几种技巧

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 你可以采用两种不同的方式将内容加到你的网站中:一种是升级现有的网页,另一种是在全新的URL中增加内容.当然,新的内容应该在搜索引擎索引的过程中会被找到,你可以采用许多措施来帮助搜索引擎更快地对新的内容关注或是新的URL.与SEO中许多新词汇一样,一个网页引起搜索引擎的关注就是代码或是获得链接.由于关于链接的对话很多,质量对数量的争论现在比任何

Android学习自定义View(五)——自定义ViewGroup及其onMeasure()的理解

MainActivity如下: package cc.testviewstudy5; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 自定义ViewGroup及其onMeasure()的理解 * * 参考资料: * 1 http://blog.csdn.net/guolin_blog/article/details/16330267 * 2 http://blog.csdn.net/dawanganba

Swift语法快速索引

在WWDC的演示中就可以看出来Swift这个更接近于脚本的语言可以用更少的代码量完成和OC同样的功能.但是对于像我一样在战争中学习战争的同学们来说,天天抱着笨Swift Programming Language Reference之类的大部头看不实际.毕竟还是要养家糊口的.而且,那么1000+页内容讲的东西不是什么都要全部在平时工作中用到的.咱们就把平时用到的全部都放在一起,忘记了立马翻开看看,不知不觉的就学会了之后变成习惯.这样多省事. 变量 1 // Variable 2 var int_v