您的当前位置:首页正文

自定义View(3) -- 字母索引

来源:花图问答

效果图:


字母索引
 public AlphabeticalIndexView(Context context) {
        this(context, null);
    }

    public AlphabeticalIndexView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AlphabeticalIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int w = (int) (getPaddingLeft() + getPaddingRight() + DisplayUtil.getTextWidth("W", mPaint));
        int h = getMeasuredHeight();
        setMeasuredDimension(w, h);
    }


    private void init(Context context) {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(DisplayUtil.sp2px(context, 15));
    }

因为不是viewGroup,所以不必重写onLayout函数,我们直接进入onDraw

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 每个字母所占用的高度
        for (int i = 0; i < mLetters.length; i++) {
            String letter = mLetters[i];
            if (letter.equals(mCurrentTouchLetter))
                mPaint.setColor(Color.BLUE);
            else
                mPaint.setColor(Color.GRAY);

            // 获取字体的宽度
            float measureTextWidth = mPaint.measureText(letter);
            // 获取内容的宽度
            int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();

            canvas.drawText(letter, getPaddingLeft() + (contentWidth - measureTextWidth) / 2, getPaddingTop()  + mSingLetterHeight * i + DisplayUtil.getTextBaseLine(mPaint), mPaint);
        }
    }

这里可能有点疑惑,为什么要用内容的宽度减去字体的宽度然后除于2,这是因为每个字母的宽度都不一样,如果不这样做的画,那么比如I就会和A W等字母左对齐,我们这样做的目的就是为了都居中。
这样我们就实现了一个静态的页面没我们要让他触摸改变,我们就重写onTouchEvent进行操作,并且添加相应的回调。

 @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                // 获取当前手指触摸的Y位置
                float fingerY = ev.getY();
                int pos = (int) (fingerY / mSingLetterHeight);
                if (pos > -1 && pos < mLetters.length && !mLetters[pos].equals(mCurrentTouchLetter)) {
                    mCurrentTouchLetter = mLetters[pos];
                    triggerTouchListener(true);
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                triggerTouchListener(false);
                break;
        }

        return true;
    }

    private void triggerTouchListener(boolean isTouch) {
        if (mTouchListener != null)
            mTouchListener.onTouch(mCurrentTouchLetter, isTouch);
    }

    // 设置触摸监听
    private SideBarTouchListener mTouchListener;

    public void setOnSideBarTouchListener(SideBarTouchListener touchListener) {
        this.mTouchListener = touchListener;
    }

    public interface SideBarTouchListener {
        void onTouch(String letter, boolean isTouch);
    }