天天看點

給予 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;
    }      

參考: