可滑动的横向时间轴

一.概述
为了项目的需求,自定义了一个seekbar可当做时间轴,且是可以支持滑动的.效果图如下:
这里写图片描述
二.重写onMessure
这里只是简单的处理了以下AT_MOST的情况.

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode == MeasureSpec.AT_MOST) {// 相当于 wrap_content
            widthSize = (int) (mStepRadius * 2 * mStepCount + getPaddingLeft() + getPaddingRight());
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            heightSize = (int) mStepRadius * 2 + getPaddingBottom()
                    + getPaddingTop();
        }
        setMeasuredDimension(widthSize, heightSize);
    }

三.绘制过程
1.首先绘制背景条,也就是最底层的颜色

        /**
     * 画背景条
     *
     * @param canvas
     *            画布
     */
    private void drawBarBg(Canvas canvas) {
        canvas.save();
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mBarColor);
        RectF r = new RectF(getPaddingLeft() + mStepRadius, getPaddingTop()
                + mStepRadius - mBarHeight / 2, getMeasuredWidth()
                - getPaddingRight() - mStepRadius, getPaddingTop()
                + mStepRadius + mBarHeight / 2);
        canvas.drawRect(r, paint);
        canvas.restore();
    }

2.绘制进度条,滑动的颜色

    /**
     * 画进度
     *
     * @param canvas
     *            画布
     */
    private void drawProgress(Canvas canvas) {
        canvas.save();
        float barWidth = getMeasuredWidth() - mStepRadius * 2
                - getPaddingLeft() - getPaddingRight();// 背景条的总宽度
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mProgressColor);
        RectF r = new RectF(getPaddingLeft() + mStepRadius, getPaddingTop()
                + mStepRadius - mBarHeight / 2, getPaddingLeft() + mStepRadius
                + barWidth * (mProgress), getPaddingTop() + mStepRadius
                + mBarHeight / 2);
        canvas.drawRect(r, paint);
        canvas.restore();
    }

3.绘制所有初始的节点

/**
     * 画节点
     *
     * @param canvas
     *            画布
     */
    private void drawSteps(Canvas canvas) {
        canvas.save();

        float barWidth = getMeasuredWidth() - mStepRadius * 2
                - getPaddingLeft() - getPaddingRight();// 背景条的总宽度
        for (int i = 0; i < mStepCount; i++) {
            int pivotX = (int) (mStepRadius + getPaddingLeft() + i * barWidth
                    / (mStepCount - 1));// 当前节点圆的中心点X坐标
            // 下面开始画圆
            mPaint.setColor(mStepNormalColor);
            RectF oval = new RectF(pivotX - mStepRadius, getPaddingTop(),
                    pivotX + mStepRadius, getPaddingTop() + mStepRadius * 2);
            canvas.drawOval(oval, mPaint);
        }
        canvas.restore();
    }

4.绘制当前滑动过的节点

    /**
     * 画当前移动的图标
     * @param canvas
     */
    private void drawCurrentStep(Canvas canvas) {
        canvas.save();
        float barWidth = getMeasuredWidth() - mStepRadius * 2
                - getPaddingLeft() - getPaddingRight();// 背景条的总宽度
        float pivotX=mStepRadius + barWidth * mProgress;
        mPaint.setColor(mStepSelectedColor);
        //这个圆可以换成自己需要的图片
        RectF oval = new RectF(pivotX - mStepRadius, getPaddingTop(),
                pivotX + mStepRadius, getPaddingTop() + mStepRadius * 2);
        canvas.drawOval(oval, mPaint);
        canvas.restore();
    }

四.滑动处理,重写了onToucheEvent方法

@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mCanDrag) {// 支持拖动
            float x = event.getX();
            //防止快速滑动出屏幕时候 不执行up的逻辑
            if (event.getAction() != MotionEvent.ACTION_UP) {
                if (x < getPaddingLeft() + mStepRadius
                        || x > getMeasuredWidth() - getPaddingRight() - mStepRadius) {
                    return true;
                }
            }

            x = x - getPaddingLeft() - mStepRadius;
            float barWidth = getMeasuredWidth() - mStepRadius * 2
                    - getPaddingLeft() - getPaddingRight();// 背景条的总宽度
            mProgress = x / barWidth;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    break;
                case MotionEvent.ACTION_UP:
                    System.out.println("up");
                    // 判断离哪个节点更近
                    int temp = mCurrentStep;
                    float minDiatance = Math.abs(mProgress);
                    for (int i = 0; i < mStepCount; i++) {
                        if (minDiatance >= (Math.abs(mProgress - i
                                / (float) (mStepCount - 1)))) {
                            minDiatance = Math.abs(mProgress - i
                                    / (float) (mStepCount - 1));
                            temp = i;
                        }
                    }
                    // 如果目前的离得最近的节点与旧的节点步数不一致,通知监听器
                    if (temp != mCurrentStep) {
                        mCurrentStep = temp;
                        if (mStepChangedListener != null) {
                            mStepChangedListener.onStepChanged(mCurrentStep);
                        }
                    }
                    mProgress = mCurrentStep / (float) (mStepCount - 1);
                    break;
            }
            invalidate();
            return true;
        } else {// 不支持拖动
            return false;
        }
    }

五.总结
上面简单的分析了以下这个自定义的过程,想看源码的移步github

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值