美文网首页
自定义View之联系人快速索引

自定义View之联系人快速索引

作者: Noblel | 来源:发表于2017-12-14 16:20 被阅读0次

需求来源

联系人快速索引

既然大家都做了快速索引,那我也来简单实现一下。

实现思路

  1. 分析元素和效果
    有侧栏有27个字母中间一个隐藏TextView,点击和滑动变色并且显示当前字母,抬手后字母消失。

  2. 确定自定义属性
    为了简单我这里就没有添加自定义属性,为了拓展和方便使用自己可以添加。

  3. 编写代码
    3.1 定义相关变量

     private String[] words = {"A", "B", "C", "D", "E", "F", "G", "H", "I",
     "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
     "W", "X", "Y", "Z", "#"};
     
     
     private int mItemHeight;
     private String mCurrentTouchWord;
     private Paint mPaint;
     private LetterTouchListener mListener;
     
     //构造方法中定义画笔
     mPaint = new Paint();
     mPaint.setAntiAlias(true);
     //sp要转成px
     mPaint.setTextSize(sp2px(12));
     mPaint.setColor(Color.BLUE);
    

    3.2 画字体(onDraw()中)

     for (int i = 0; i < words.length; i++) {
         //根据每个字体的高度画
         int letterCenterY = i * mItemHeight + mItemHeight / 2 + getPaddingTop();
         Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
         int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
         int baseLine = letterCenterY + dy;
         int textWidth = (int) mPaint.measureText(words[i]);
         int x = getWidth() / 2 - textWidth / 2;
         //当前字母高亮(最好用两个画笔,因为mPaint.setColor是调用native方法)
         if (words[i].equals(mCurrentTouchWord)) {
             mPaint.setColor(Color.RED);
             canvas.drawText(words[i], x, baseLine, mPaint);
         } else {
             mPaint.setColor(Color.BLUE);
             canvas.drawText(words[i], x, baseLine, mPaint);
         }
     }
    

    3.3 处理尺寸(onMeasure())

     //计算宽度 = 左右的padding + 字母的宽度(取决画笔大小)
     int textWidth = (int) mPaint.measureText("A");
     int width = getPaddingLeft() + getPaddingRight() + textWidth;
     int height = MeasureSpec.getSize(heightMeasureSpec);
     //去除padding
     mItemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / words.length;
     setMeasuredDimension(width, height);
    

    3.4 处理点击事件(onTouchEvent())

      switch (event.getAction()) {
         //手指移动
         case MotionEvent.ACTION_MOVE:
             float Y = event.getY();
             //字母索引
             int index = (int) (Y / mItemHeight);
             //由于getY可能是-100多等所以要做额外处理
             if (index < 0)
                 index = 0;
             if (index > words.length - 1)
                 index = words.length - 1;
             if (!words[index].equals(mCurrentTouchWord)) {
                 mCurrentTouchWord = words[index];
                 if (mListener != null)
                     //定义触摸接口
                     mListener.touch(mCurrentTouchWord, true);
                 //刷新界面
                 invalidate();
             }
             break;
         //抬手动作
         case MotionEvent.ACTION_UP:
             if (mListener != null)
                 mListener.touch(mCurrentTouchWord, false);
             break;
     }
     //消费事件,事件分发机制单独会写一篇
     return true;
    

    3.5 接口

     public interface LetterTouchListener {
         void touch(CharSequence letter, boolean isTouch);
     }
    

全部源码:

快速索引源码

相关文章

网友评论

      本文标题:自定义View之联系人快速索引

      本文链接:https://www.haomeiwen.com/subject/cqbkwxtx.html