仿小米通讯录 右侧滑动条与带动画的悬停列表实现(一)

先来看右侧滑动条布局

<com.reige.addressbook.IndexBar
        android:layout_alignParentRight="true"
        android:layout_width="20dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"/>

然后我们创建一个类继承View来绘制右侧字母导航滑动条

//初始化的方法
private void init() {
        //抗锯齿
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //设置绘制的文字大小
        mPaint.setTextSize(30);
        mPaint.setColor(Color.BLUE);
        //因为默认的文字绘制锚点在文字的左下角,这样会使文字的左边在一条直线上 因为字母的宽度不同会使绘制出的字母看上去比较乱 这个方法可以将锚点设置到文字底部中心 从而避免这个问题
        mPaint.setTextAlign(Paint.Align.CENTER);
    }

看上去比较乱

绘制简单原理
这里写图片描述

public class IndexBar extends View {

    private OnSlideListener onSlideListener;
    private String[] arr = {"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 Paint mPaint;
    private int mWidth;
    private float mBoxHeight;

    public IndexBar(Context context) {
        super(context);

    }

    public IndexBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public IndexBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(30);
        mPaint.setColor(Color.BLUE);
        //因为默认的文字绘制锚点在文字的左下角,这样会使文字的左边在一条直线上 因为字母的宽度不同会使绘制出的字母看上去比较乱 这个方法可以将锚点设置到文字底部中心 从而避免这个问题
        mPaint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = getMeasuredWidth();
        mBoxHeight = getMeasuredHeight() * 1f / arr.length;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < arr.length; i++) {
            float textHeight = getTextHeight(arr[i]);
            float x = mWidth / 2;
            float y = (1 + i) * mBoxHeight;
            mPaint.setColor(lastIndex==i?Color.RED:Color.BLUE);


            canvas.drawText(arr[i], x, y, mPaint);
        }
    }

    private int lastIndex = -1;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:

                float y = event.getY();
                //获取当前点击第几个item
                int index = (int) (y / mBoxHeight);
                if (lastIndex != index) {
                    if (index >= 0 && index < arr.length) {
                        Log.e("index", "index:::" + index);

                        //选择的letter变化 回调
                        if(onSlideListener!=null){
                            onSlideListener.onSlide(arr[index]);
                        }

                    }
                }
                lastIndex = index;
                break;
            case MotionEvent.ACTION_UP:
                lastIndex = -1;
                break;
        }

        invalidate();
        return true;
    }

    /**
     * @param text
     * @return 返回文字的高
     */
    private float getTextHeight(String text) {
        Rect rect = new Rect();
        mPaint.getTextBounds(text, 0, text.length(), rect);
        return rect.height();
    }

    /**
     * 设置监听的方法
     */
    public interface OnSlideListener{
        void onSlide(String letter);
    }

    /**
     * 滑动监听
     * @param osl
     */
    public void setOnSlideListener(OnSlideListener osl){
        this.onSlideListener = osl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值