zoukankan      html  css  js  c++  java
  • 快速索引 (对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;
                    }
                }
    
  • 相关阅读:
    CF601B Solution
    CF847F Solution
    CF877D Solution
    CF1472F Solution
    CF1472G Solution
    CF1355E Solution
    CF912D Solution
    CF1167F Solution
    shell脚本自动备份MySQL数据库
    centos7 crontab笔记
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314899.html
Copyright © 2011-2022 走看看