Android自定义View实现快速索引功能

前言

源码Demo:请点击此处

先看下效果吧~
1806065-20190927131811291-1215858161.gif

功能实现疑难点分析

分析:

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

转载于:https://www.cnblogs.com/io1024/p/11597407.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值