I want to make a custom round progress bar.

enter image description here

Found an example of such a custom progress bar,

enter image description here

Can I rewrite this code to get the result I need, I need the number of blue circles to be different depending on the set value. I try to change the code but do not fully understand what needs to be done, I try to replace drawing with a rectangle on the onDraw method a circle, but I still don’t understand how to get the result I need. Here is the custom bar code that I showed above:

 public class CircleSegmentBar extends ProgressView { public static final int rad_360 = 360; private float SEGMENT_WIDTH = 3f; private int PADDING = 10; private Path progressPath; private Path backgroundPath; final RectF oval = new RectF(); private float radius; private float angle; private int angleStartPoint = ProgressStartPoint.DEFAULT.getValue(); private float left; private float top; private float right; private float bottom; private boolean isGradientColor; public CircleSegmentBar(Context context) { super(context); } public CircleSegmentBar(Context context, AttributeSet attrs) { super(context, attrs); } @Override void init() { initBackgroundColor(); initForegroundColor(); progressPath = new Path(); backgroundPath = new Path(); } @Override protected void onSizeChanged(int width, int height, int oldw, int oldh) { if (width > height) { radius = height / 3; } else { radius = width / 3; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); left = 0 + strokeWidth / 2; top = 0 + strokeWidth / 2; right = min - strokeWidth / 2; bottom = min - strokeWidth / 2; oval.set(left + PADDING, top + PADDING, right - PADDING, bottom - PADDING); } @Override public void onDraw(Canvas canvas) { drawGradientColor(); drawCircle(canvas); } private void drawCircle(Canvas canvas) { backgroundPath.reset(); for (int i = 0; i < rad_360; i += 5) { backgroundPath.addArc(oval, i, SEGMENT_WIDTH); } canvas.drawPath(backgroundPath, backgroundPaint); progressPath.reset(); angle = rad_360 * (int) progress / maximum_progress + angleStartPoint; for (int i = angleStartPoint; i < angle; i += 5) { // progressPath.addArc(oval, i, SEGMENT_WIDTH); Log.wtf("Width: " + getWidth(), "Height: " + getHeight()); progressPath.addCircle(getWidth() / 2 , getHeight() /2 , 20 , Path.Direction.CW); } canvas.drawPath(progressPath, foregroundPaint); drawText(canvas); } public void setCircleViewPadding(int padding) { PADDING = padding; invalidate(); } public float getSegmentWidth() { return SEGMENT_WIDTH; } /*** * @ ***/ public void setSegmentWidth(float segment_width) { SEGMENT_WIDTH = segment_width; } public int getPadding() { return PADDING; } // *******************START POSITION FOR CIRCLE AND CIRCLE SEGMENT // VIEW****************** public int getProgressStartPosition() { return startPosInDegrees; } public void setStartPositionInDegrees(int degrees) { this.startPosInDegrees = degrees; } public void setStartPositionInDegrees(ProgressStartPoint position) { this.startPosInDegrees = position.getValue(); } private void drawGradientColor() { if (isGradientColor) setLinearGradientProgress(gradColors); } public void setLinearGradientProgress(boolean isGradientColor) { this.isGradientColor = isGradientColor; } public void setLinearGradientProgress(boolean isGradientColor, int[] colors) { this.isGradientColor = isGradientColor; gradColors = colors; } private void setLinearGradientProgress(int[] gradColors) { if (gradColors != null) colorHelper.setGradientPaint(foregroundPaint, left, top, right, bottom, gradColors); else colorHelper.setGradientPaint(foregroundPaint, left, top, right, bottom); } @Override public ShapeType setType(ShapeType type) { // TODO Auto-generated method stub return ShapeType.SEGMENT_CIRCLE; } } 

Drawing a single dilation occurs as I understand it in this place:

 progressPath.addArc(oval, i, SEGMENT_WIDTH); 

And I need to draw a circle

 progressPath.addCircle(x, x, radius , Path.Direction.CW); 

How can I make a replacement?

  • I am not very well versed in the Android OS, but judging by the code section you specified and the documentation viewed diagonally, the method itself draws an arc with an offset (the cycle itself participates in the offset and the step is 5) it is logical that the number of diameters you are interested in should be proportional to this step ( or any) well, then calculate the length of the path traveled and find the coordinates of the highlighted (according to the idea of ​​a previously drawn circle and fill it with color relative to progress) should be a simple task. to create a visual code under Fx for example - Peter Slusar
  • @PeterSlusar I will be glad to any help - Kirill Stoianov

1 answer 1

Here is a rough example of the method described in the comment (JavaFx):

 private void setProgress(double progress) { //Вычисляем количество видимых частей int visiblePiece = (int) (360 * progress / (360 / pieces)); for (double i = 0; i < visiblePiece; i++) { // Порождаем обект круга в конструктор передаем кординаты нового обекта. // Угол поворота можно учесть здесь же Circle c = new Circle(center, center - radius, 10, Color.AQUA); // или позже c.getTransforms().add(Translate.rotate(i * stepAngle, center, center)); // Добавляем объект на сцену pane.getChildren().add(c); } } 

i.e. we calculate the number of already visible full circles and add them to the scene in the cycle. Just in case I remind you that you can calculate the X / Y coordinates of a point on the circle through the sine and cosine of the angle * by the radius. In order not to redraw all the objects with a tiny changing progress, you can save the state already from drawn circles (or realize changing the brightness of the fill, for example) Well, I recommend it when drawing graphics if possible to work with stream api (although it seems like it is not possible in an aneroid)

Result (0.9):

enter image description here