// move to bottom center mArrowPath.moveTo(halfArrowWidth, 0); // rect bottom left edge mArrowPath.lineTo(rectPaddingLeft, 0); // rect left edge mArrowPath.lineTo(rectPaddingLeft, rectHeight); // tri bottom left edge mArrowPath.lineTo(triPaddingLeft, rectHeight); // tri left edge mArrowPath.lineTo(halfArrowWidth, arrowHeight); // tri right edge mArrowPath.lineTo(arrowWidth - triPaddingLeft, rectHeight); // tri bottom right edge mArrowPath.lineTo(arrowWidth - rectPaddingLeft, rectHeight); // rect right edge mArrowPath.lineTo(arrowWidth - rectPaddingLeft, 0); // rect right bottom edge mArrowPath.lineTo(halfArrowWidth, 0);
int layoutCont = canvas.saveLayer(mCircleRectF, mDefaultPaint, Canvas.ALL_SAVE_FLAG); mDefaultPaint.setColor(mLoadingCircleBackColor); canvas.drawCircle(mCircleRectF.centerX(), mCircleRectF.centerY(), mCircleRadius, mDefaultPaint); mDefaultPaint.setXfermode(mXfermode); // draw bg circle 2 int innerCircleRadius = (int) (mCircleRadius * innerCircleScalingFactor); canvas.drawCircle(mCircleRectF.centerX(), mCircleRectF.centerY(), innerCircleRadius, mDefaultPaint); mDefaultPaint.setXfermode(null); canvas.restoreToCount(layoutCont);
private void updateCircleToLinePath(Path linePath, int circleDiameter, float normalizedTime) {
if (linePath == null) {
return;
}
int index = 0;
float adjustNormalizedTime = 0;
if (normalizedTime <= CIRCLE_TO_LINE_SEASONS[1]) {
adjustNormalizedTime = normalizedTime / CIRCLE_TO_LINE_SEASONS[1];
} else if (normalizedTime < CIRCLE_TO_LINE_SEASONS[2]) {
index = 1;
adjustNormalizedTime = (normalizedTime - CIRCLE_TO_LINE_SEASONS[1])
/ (CIRCLE_TO_LINE_SEASONS[2] - CIRCLE_TO_LINE_SEASONS[1]);
} else {
index = 2;
adjustNormalizedTime = (normalizedTime - CIRCLE_TO_LINE_SEASONS[2])
/ (CIRCLE_TO_LINE_SEASONS[3] - CIRCLE_TO_LINE_SEASONS[2]);
}
// the path bounds width
int boundWidth = (int) (((CIRCLE_TO_LINE_WIDTH_FACTOR[index + 1]
- CIRCLE_TO_LINE_WIDTH_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_WIDTH_FACTOR[index]) * circleDiameter);
// the distance of cubic line1‘ x1 to cubic line2‘s x2
int adjustBoundWidth = boundWidth;
if (normalizedTime <= CIRCLE_TO_LINE_SEASONS[1]) {
adjustBoundWidth = (int) (boundWidth * adjustNormalizedTime);
}
// the path bounds height
int boundHeight = (int) (((CIRCLE_TO_LINE_HEIGHT_FACTOR[index + 1]
- CIRCLE_TO_LINE_HEIGHT_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_HEIGHT_FACTOR[index]) * circleDiameter);
// calculate the four points
float firstControlXFactor = (CIRCLE_TO_LINE_FST_CON_X_FACTOR[index + 1]
- CIRCLE_TO_LINE_FST_CON_X_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_FST_CON_X_FACTOR[index];
float firstControlYFactor = (CIRCLE_TO_LINE_FST_CON_Y_FACTOR[index + 1]
- CIRCLE_TO_LINE_FST_CON_Y_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_FST_CON_Y_FACTOR[index];
float secondControlXFactor = (CIRCLE_TO_LINE_SEC_CON_X_FACTOR[index + 1]
- CIRCLE_TO_LINE_SEC_CON_X_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_SEC_CON_X_FACTOR[index];
float secondControlYFactor = (CIRCLE_TO_LINE_SEC_CON_Y_FACTOR[index + 1]
- CIRCLE_TO_LINE_SEC_CON_Y_FACTOR[index])
* adjustNormalizedTime + CIRCLE_TO_LINE_SEC_CON_Y_FACTOR[index];
int firstControlX = (int) (circleDiameter * firstControlXFactor);
int firstControlY = (int) (circleDiameter * firstControlYFactor);
int secondControlX = (int) (circleDiameter * secondControlXFactor);
int secondControlY = (int) (circleDiameter * secondControlYFactor);
linePath.reset();
// left line
linePath.cubicTo(firstControlX, firstControlY,
secondControlX, secondControlY, adjustBoundWidth / 2, boundHeight);
// left right line
linePath.cubicTo(adjustBoundWidth - secondControlX,
secondControlY, adjustBoundWidth - firstControlX, firstControlY, adjustBoundWidth, 0);
// translate path to move the origin to the center
int offsetX = (circleDiameter - adjustBoundWidth) / 2;
int offsetY = (circleDiameter - boundHeight) / 2;
linePath.addCircle(firstControlX, firstControlY,3, Path.Direction.CW);
linePath.addCircle(secondControlX, secondControlY,3, Path.Direction.CW);
linePath.addCircle(adjustBoundWidth - secondControlX,
secondControlY,3, Path.Direction.CW);
linePath.addCircle(adjustBoundWidth - firstControlX, firstControlY,3, Path.Direction.CW);
linePath.offset(offsetX, offsetY);
}
if (mArrowMovePath.isEmpty()) { mArrowMovePath.moveTo(mArrowMovePathRect.left, mArrowMovePathRect.bottom); mArrowMovePath.cubicTo(mArrowMovePathRect.left + mArrowMovePathRect.width() / 4, mArrowMovePathRect.top, mArrowMovePathRect.right, mArrowMovePathRect.top, mArrowMovePathRect.right, mArrowMovePathRect.bottom); mArrowPathMeasure.setPath(mArrowMovePath, false); mArrowMovePathLength = mArrowPathMeasure.getLength(); } mArrowPathMeasure.getPosTan(mArrowMovePathLength * normalizedTime , mArrowMovePoint, null);
private void drawProgressRopePath( Canvas canvas, float normalizeProgress, int baselineLen, int baseLineX, int baseLineY, int highestPointHeight, int leftLineColor) { int halfLen = baselineLen / 2; int middlePointX = (int) (baseLineX + baselineLen * normalizeProgress); int middlePointY; float k = (float) highestPointHeight / halfLen; if (normalizeProgress < HALF_NORMALIZED_PROGRESS) { middlePointY = (int) (halfLen * k * normalizeProgress / HALF_NORMALIZED_PROGRESS) + baseLineY; } else { middlePointY = (int) (halfLen * k * (1 - normalizeProgress) / HALF_NORMALIZED_PROGRESS) + baseLineY; } // draw right part first mBaseLinePaint.setColor(DEFAULT_LOADING_LINE_COLOR); canvas.drawLine(middlePointX, middlePointY, baseLineX + baselineLen, baseLineY, mBaseLinePaint); // draw left part mBaseLinePaint.setColor(leftLineColor); canvas.drawLine(baseLineX, baseLineY, middlePointX, middlePointY, mBaseLinePaint); if (mProgressRopePathRectF == null) { mProgressRopePathRectF = new RectF(); } mProgressRopePathRectF.set(baseLineX, baseLineY, baseLineX + baselineLen, middlePointY); }
Path cycle = new Path(); // generate bomb point shape cycle.addCircle(0, 0, mBaseLineStrokeWidth / 2, Path.Direction.CCW); cycle.addCircle(mBaseLineStrokeWidth, 0, mBaseLineStrokeWidth / 3, Path.Direction.CCW); cycle.addCircle(mBaseLineStrokeWidth * 2, 0, mBaseLineStrokeWidth / 4, Path.Direction.CCW); cycle.addCircle(mBaseLineStrokeWidth * 3, 0, mBaseLineStrokeWidth / 5, Path.Direction.CCW); mFailedBombPaint = new Paint(); mFailedBombPaint.setStrokeWidth(mBaseLineStrokeWidth); mFailedBombPaint.setAntiAlias(true); mFailedBombPaint.setColor(DEFAULT_PROGRESS_LINE_LEFT_COLOR); mFailedBombPaint.setStyle(Paint.Style.STROKE); mFailedBombPaint.setPathEffect(new PathDashPathEffect(cycle, mBaseLineStrokeWidth * 3, 0, PathDashPathEffect.Style.TRANSLATE)); mFailedBombBellowPaint = new Paint(mFailedBombPaint); mFailedBombBellowPaint.setPathEffect(new PathDashPathEffect(cycle, mBaseLineStrokeWidth * 3, HALF_FULL_ANGLE, PathDashPathEffect.Style.TRANSLATE));
float angle; String str; if (normalizedTime <= HALF_NORMALIZED_PROGRESS) { str = FULL_PROGRESS_STR; angle = HALF_FULL_ANGLE * normalizedTime; mProgressTextPaint.setColor(DEFAULT_PROGRESS_TEXT_COLOR); } else { str = FULL_PROGRESS_DONE_STR; angle = HALF_FULL_ANGLE * normalizedTime + HALF_FULL_ANGLE; mProgressTextPaint.setColor(DEFAULT_DONE_PROGRESS_TEXT_COLOR); } if (mCamera == null) { mCamera = new Camera(); } mCamera.save(); mCamera.rotateY(angle); mCamera.getMatrix(mArrowRotateMatrix); mCamera.restore(); // 保证绕Arrow的中心进行旋转 mArrowRotateMatrix.preTranslate(-mArrowRectF.centerX(), -mArrowRectF.centerY()); mArrowRotateMatrix.postTranslate(mArrowRectF.centerX(), mArrowRectF.centerY()); mLastArrowOffsetX = (int) (mBaseLineX + mBaseLineLen - mArrowRectF.width() / 2); mLastArrowOffsetY = (int) (mBaseLineY - mArrowRectF.height()); canvas.save(); canvas.translate(mLastArrowOffsetX, mLastArrowOffsetY); // 应用上述Camera变换的结果 canvas.concat(mArrowRotateMatrix); mDefaultPaint.setColor(DEFAULT_ARROW_COLOR); // 绘制Arrow canvas.drawPath(mArrowPath, mDefaultPaint); mProgressTextPaint.getTextBounds(str, 0, str.length(), mProgressTextRect); // 文字 canvas.drawText(str, mArrowRectF.left + (mArrowRectF.width() - mProgressTextRect.width()) / 2, mArrowRectF.bottom - mArrowRectF.height() / 2, mProgressTextPaint); canvas.restore();
<declare-styleable name="GADownloadingView"> <attr name="arrow_color" format="color" /> <attr name="loading_circle_back_color" format="color" /> <attr name="loading_line_color" format="color" /> <attr name="progress_line_color" format="color" /> <attr name="progress_text_color" format="color" /> <attr name="done_text_color" format="color" /> </declare-styleable>
原文:http://blog.csdn.net/tianjian4592/article/details/53699988