zoukankan      html  css  js  c++  java
  • Android自定义View实现快速索引功能

    前言

    源码Demo:请点击此处

    先看下效果吧~

    功能实现疑难点分析

    分析:

    1. 假设:控件 高度 均分成 26个 方块,方块的宽度和控件宽度相同。
    2. 假设:每个字母 被一个方形的单元格 贴边包裹。单元格在方块内居中。
    3. 每个字母的坐标(X轴、Y轴)是其左下角的位置,也就是单元格的左下角位置。
    • 以 A 为例:0 索引
      x轴坐标:float x = measuredWidth * 0.5f - textWidth * 0.5f (控件宽度的一半 - 单元格宽度的一半)
      y轴坐标:float y = cellHeight * 0.5f + textWidth * 0.5f (控件宽度的一半 + 单元格宽度的一半)
    • 以 B 为例:1 索引
      x轴坐标:float x = measuredWidth * 0.5f - textWidth * 0.5f (控件宽度的一半 - 单元格宽度的一半)
      y轴坐标:float y = cellHeight * 0.5f + textWidth * 0.5f + i * cellHeight (控件宽度的一半 + 单元格宽度的一半 + 前面所有单元格的高度)

    说明: measuredWidth - 整个自定义控件的宽度;cellHeight - 单元格的高度;textWidth - 单个字母的宽度(通过画笔可以获取)

    • 26个字母的绘制,并确定每个字母的位置
      部分代码示例(具体的实现还请参考Demo)
    //绘制 A-Z
    for (int i = 0; i < LETTERS.length; i++) {
        String letter = LETTERS[i];
        //计算每个字母的坐标位置,通过画笔可以获取字母的宽度:measureText()
        float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
        //获取指定字符串指定区域的宽高信息
        Rect rect = new Rect();
        paint.getTextBounds(letter, 0, letter.length(), rect);
        //获取字母的高度
        int textHeight = rect.height();
        //获取字母的宽度 和 paint.measureText(letter) 结果一样
        //int textWidth = rect.width();
        float y = cellHeight * 0.5f + textHeight * 0.5f + i * cellHeight;
    
        //【改变选择字母】字母被选中时,重绘字母时,改变字母状态
        paint.setColor(i == currentIndex ? Color.GRAY : Color.WHITE);
    
        canvas.drawText(letter, x, y, paint);
    }
    
    • 产生触摸事件时,确定被选中的位置
      private void getCurrentIndex(MotionEvent event) {
            //获取当前所处位置的-Y轴-坐标(取值可能会小于0)
            float y = event.getY();
            //得到当前触摸位置是第几个索引位置
            int index = (int) (y / cellHeight);
            //获取当前索引和上次获取索引对比,相同则不处理
            if (index != currentIndex) {
                if (index >= 0 && index < LETTERS.length) {
                    currentIndex = index;
                    //设置一个监听回调:返回当前被选中的字母(也可以处理其他业务)
                    if (updateListener != null) {
                        updateListener.onLetterUpdate(LETTERS[index]);
                    }
                }
            }
        }
    
    • 在 activity 中监听回调,并把 listView 和 自定义控件结合起来
        @Override
        public void onLetterUpdate(String letter) {
            showCustomToast(letter); //自定义的一个Toast(可以查看Demo)
            //触摸监听回调
            //找到数据集合中首次出现letter的索引位置,listView直接跳到该索引位置
            for (int index = 0; index < persons.size(); index++) {
                String pin = persons.get(index).getNamePinYin().charAt(0) + "";
                if (TextUtils.equals(pin, letter)) {
                    listView.setSelection(index);
                    break;
                }
            }
        }
    

    PS:好了,到这里,一个简单的自定义快速索引功能就实现了。很高兴能在这里和大家分享以及互相学习。

  • 相关阅读:
    网卡
    java调用函数参数的传递机制及java内存管理
    zookeeper安装遇到的问题
    tcp/ip,http,socket mysql底层技术原理
    前台页面
    权限模块设计及使用
    spring security学习,使用过程
    mybatis处理集合、循环、数组和in等语句的使用
    sql语句的一些学习
    java 实现获取当天,当周,当月,当季,当年的时间段
  • 原文地址:https://www.cnblogs.com/io1024/p/11597407.html
Copyright © 2011-2022 走看看