Custom View — Rating Star fills from left to right based on percentage — part 3(5 parts)

This is part 3 in the series of custom view tutorials. There was need of rating star in one of my app that fills from left to right based on percentage something like below.

Screenshot_2014-10-11-22-05-53

You got an idea…! I tried much more ways to achieve this but none of them worked for me. At last these steps I followed.
1) Draw star(inner) with Blue color (with paint FILL).
2) Draw a rect above this Star which hides inner star completely.
3) Based on percentage left side of the rect is modified from its original position.
4) Again an outer star with Gray color (with paint STROKE) is drawn.

Stars are drawn based on this blog post author made use of circles to draw stars.

Inner & Outer stars
Drawing is nothing moving Path based on calculations in a canvas (with specified bitmap to draw into). Here is the code. Inner star is drawn with FILL paint and Outer star is drawn with STROKE paint refer source code for more.

private void drawInnerFillStarInTempCanvas() {
bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas(bitmap);
int measuredWidth = getWidth();
int measuredHeight = getHeight();
int x = (measuredWidth / 2);
int y = (measuredHeight / 2);
int outerRadius = measuredWidth / 4;
int innerRadius = outerRadius / 3;
int points = 5, fillPercent = 1;
if (points < 3)
return;
float a = (float) (Math.PI * 2) / (points * 2);
int workingRadius = outerRadius;
polyPath.reset();
tempCanvas.translate(x, y);
for (int j = 0; j < ((fillPercent < 1) ? 2 : 1); j++) {
polyPath.moveTo(workingRadius, 0);
for (int i = 1; i < points * 2; i++) {
workingRadius = (workingRadius == outerRadius) ? innerRadius : outerRadius;
float xPt = (float) (workingRadius * Math.cos(a * i));
float yPt = (float) (workingRadius * Math.sin(a * i));
polyPath.lineTo(xPt, yPt);
}
polyPath.close();
outerRadius -= outerRadius * fillPercent;
innerRadius = outerRadius / 2;
a = -a;
}
float startAngle = 126;
tempCanvas.rotate(startAngle);
tempCanvas.drawPath(polyPath, innerStarPaint);
}

Drawing Rect to hide inner star
This rect will hide the star which we drawn, by changing the left side of this rect we can show portion of star.

private void formHidingRectAroundStar(int screenWidth, int screenHeight, int outerRadius) {
rectLeft = screenWidth —(screenWidth / 2 + outerRadius —25);
rectRight = (screenWidth / 2 + outerRadius) —25;
rectTop = screenHeight —(screenHeight / 2 + outerRadius);
rectBottom = screenHeight / 2 + outerRadius;
rectWidthIs = rectRight —rectLeft;
rect.set(rectLeft, rectTop, rectRight, rectBottom);
}

screenWidth, screenHeight, outerRadius, rectWidthIs are required attributes. Rect drawn when the view is instantiated as below.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// where as getWidth() / 4 is also outer radius of Outer circle of Star
formHidingRectAroundStar(getWidth(), getHeight(), getWidth() / 4);
}

From Activity this method is called periodically, which sets 4 sides of the rect.

// from activity
public void setRectLeftSideValue() {
int factor = rectWidthIs / 50;
rectLeft += factor;
rect.set(rectLeft, rectTop, rectRight, rectBottom);
}

OnDraw method

@Override
protected void onDraw(Canvas canvas) {
// drawing innerStar using Canvas
drawInnerFillStarInTempCanvas();
canvas.drawBitmap(bitmap, 0, 0, innerStarPaint);
// drawing hiding rect
canvas.drawRect(rect, rectPaint);
// drawing outerStar using Canvas
drawOuterStrokeStarInTempCanvas();
canvas.drawBitmap(bitmap, 0, 0, outerStarPaint);
}

Runnable which is called from Activity

Runnable runnable = new Runnable() {

@Override
public void run() {
if (value <= 50) {
if (value < 10) {
((TextView) findViewById(R.id.RatingTxtView)).setText(“ 0.”+value);
} else {
((TextView) findViewById(R.id.RatingTxtView)).setText(String.valueOf(value / 10) +”.”
+String.valueOf(value % 10));
}
ratingStar.setRectLeftSideValue();
value++;
ratingStar.invalidate();
myHandler.postDelayed(this, 3);
}
}
};

You can make use of my work if needed, after some time I may tweak it more to look & work better.
Source code is available at github.

Enjoy Happy coding!!!

--

--