需求: 根據的服務端傳回 百分比進行旋轉。在旋轉結束後展示目前點的百分比。并且在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;
}
參考: