天天看点

给予 HoloCircularProgressBar 实现自定义 标签展示

给予 HoloCircularProgressBar 实现自定义 标签展示
给予 HoloCircularProgressBar 实现自定义 标签展示

需求: 根据的服务端返回 百分比进行旋转。在旋转结束后展示当前点的百分比。并且在0~50% 标签在右边 50%~100% 在左边。根据进度不同需要绘制两个不同的颜色

需要熟悉的Api view 绘制流程 Canvas paint Matrix ,简单数学计算 已知圆心半径 弧度求圆上任意点(x,y) 坐标。

最主要是一种解决问题思路和 不怕麻烦。

主要修改 HoloCircularProgressBar 类中 mesure() 和 ondraw()下面贴出来核心代码:

@Override
    protected void onDraw(final Canvas canvas) {

        canvas.translate(mTranslationOffsetX, mTranslationOffsetY);

        final float progressRotation = getCurrentRotation();
        if (progress < MAX_END_FLOAT_VALUE) {
            canvas.drawArc(mCircleBounds, 0, 360, false, mBackgroundColorPaint);
        }
        if (!mOverrdraw) {
        } else {

    canvas.drawArc(mCircleBounds, 270, progressRotation, false,                  mProgressColorPaint);
            //canvas.drawArc(mCircleBounds, 270, progressRotation - 360, false, mProgressColorPaint); 两周
        }
        if (isCircleEnabled()) {
            canvas.save();
            // rotate the square by 45 degrees
            canvas.rotate(progressRotation - 90);
            // canvas.rotate(45, mCirclePosX, mCirclePosY);
            mSquareRect.left = mCirclePosX - mCircleRadius / 3;
            mSquareRect.right = mCirclePosX + mCircleRadius / 3;
            mSquareRect.top = mCirclePosY - mCircleRadius / 3;
            mSquareRect.bottom = mCirclePosY + mCircleRadius / 3;

            float x = mSquareRect.left + (mSquareRect.right - mSquareRect.left) / 2;
            float y = mSquareRect.top + (mSquareRect.bottom - mSquareRect.top) / 2;
            canvas.drawCircle(x, y, getResources().getDimensionPixelSize(R.dimen.circle_7), mThumbColorPaint);

            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(getResources().getColor(R.color.text_white));
            canvas.drawCircle(x, y, getResources().getDimensionPixelSize(R.dimen.circle_6), paint);
            canvas.restore();      

这里修改了 原来的ondraw() 绘制圆环的方式。实现起来更容易理解,

canvas.drawArc(mCircleBounds, 0, 360, false, mBackgroundColorPaint);

画圆环

canvas.drawArc(mCircleBounds, 270, progressRotation, false, mProgressColorPaint);

画外层圆环,至于为什么从270 度 开始。以为 270度正好从圆环顶部开始画。

接下来画小圆和小圆上的白点。 根据算好的偏移量。就好了

主要的代码

/**
     * 画标签
     *
     * @param canvas
     * @param x
     * @param y
     * @param paint  画笔
     */
    private void drawTag(Canvas canvas, float x, float y, Paint paint) {

        canvas.rotate(270);
        //计算小圆半径 进行回调
        double x2 = mRadius * Math.cos(getProgress() * Math.PI * 2);
        double y2 = mRadius * Math.sin(getProgress() * Math.PI * 2);

        Matrix matrix = new Matrix();
        if ((progress > 0.5f && progress <= 1f)) {
            matrix.setTranslate((float) x2 + getResources().getDimension(R.dimen.width_f1), (float) y2);
            TextView rightView = (TextView) View.inflate(MyApp.getInstance().getApplicationContext(), R.layout.view_right_progress_tag, null);
            rightView.setText(endPercent + "%");
            matrix.postRotate(90, (float) x2 + getResources().getDimension(R.dimen.width_25), (float) y2 - getResources().getDimension(R.dimen.width_14));
            canvas.drawBitmap(convertViewToBitmap(rightView), matrix, paint);
        } else {
            matrix.setTranslate((float) (20f + x2), (float) y2);
            TextView leftView = (TextView) View.inflate(MyApp.getInstance().getApplicationContext(), R.layout.view_left_progress_tag, null);
            leftView.setText(endPercent + "%");
             matrix.postRotate(90, (float) x2, (float) y2);
            canvas.drawBitmap(convertViewToBitmap(leftView), matrix, paint);
        }
        canvas.restore();

        LogUtil.d(TAG, "小圆圆心坐标" + " (" + x2 + "," + y2 + ")" +
                "大圆圆心坐标 = (" + mTranslationOffsetX + "," + mTranslationOffsetY + ")" + "大圆半径=" + mRadius + "旋转角度=" + getCurrentRotation());
    }      

首先旋转画布。根据数学公式计算出圆环上的圆心点(x1,y1)准备画标签。

Eg:只是这个标签费和好长时间,一直没有想出好的方式,最后使用matrix 解决了。让标签绕着小圆的圆心旋转。和偏移。之前一直绕着大圆旋转。造成标签不能水平放置,会有一个旋转角度。

标签是左右两边各一个,为什么? 方便setText()。否则标签里面的百分比会有旋转。这里需要一个工具类: view 转 bitmap 的方法

/**
     * view 转换为 bitmap
     *
     * @param view
     * @return
     */
    public static Bitmap convertViewToBitmap(View view) {
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();

        return bitmap;
    }      

参考: