0

I am trying to create a custom loading screen. The pink line on the arc should start from the left and progresses to the right, which should occur over a specific time span that I've set as a variable.

I've attempted to implement this using android.graphics.drawable, please suggest some ideas or the directions I should approach this task.

before loading

after loading

djmonki
  • 3,020
  • 7
  • 18

1 Answers1

0

I finally made a custom View to achieve that:

public class ArcProgressView extends View {
    private int width;
    private float startAngle;
    private float endAngle;
    private float progressAngle;
    private RectF bounds;

    private Paint circlePaint;
    private Paint textPaint;

    private float progress;

    public ArcProgressView(Context context, AttributeSet attributeSet) {
        super(context,attributeSet);
        init();
    }

    public void init(){
        circlePaint = new Paint();
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(15);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);
        circlePaint.setColor(Color.rgb(254,54,115));

        textPaint = new Paint();
        textPaint.setColor(Color.rgb(254,54,115));
        textPaint.setTextSize(50);

        calcBounds();
    }

    private void calcBounds(){
        int offsetY = 300; // The amount of Y offset
        int offset = 400; // the amount of circle offscreen
        // Tweak as you prefer

        bounds = new RectF(0,offsetY,width+offset,width+offset+offsetY);
        bounds.offset(-offset /2 ,0);

        float r = bounds.width()/2; //the radius of the circle
        float x = width/2;

        float startY = (float) (bounds.centerY() - Math.sqrt(r * r - x * x));

        startAngle = (float) (180 / Math.PI * Math.atan2(startY - bounds.centerY() , 0 - bounds.centerX()));
        endAngle = (float) (180 / Math.PI * Math.atan2(startY - bounds.centerY() , width - bounds.centerX()));

    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(width != getWidth()) {
            width = getWidth();
            calcBounds();
        }

        canvas.drawArc(bounds,startAngle, progressAngle,false,circlePaint);
        String progressText = (int)progress + "%";
        canvas.drawText(progressText,bounds.centerX() - textPaint.measureText(progressText) / 2,bounds.centerY(),textPaint);
        super.onDraw(canvas);
    }

    public void setProgress(float progress){
        this.progress = progress;
        progressAngle = (endAngle-startAngle)*(progress/100f);
        invalidate();
    }

}

the result looks like this

enter image description here

How is it done?

  1. We create a RectF bigger than screen width by some offset (this will contain our circle)
  2. We calculate the Y intersection of the circle with the screen bounds with (float) (bounds.centerY() - Math.sqrt(r * r - x * x));
  3. We calculate the angle between the start and ending point using Math.atan2()
startAngle = (float) (180 / Math.PI * Math.atan2(startY - bounds.centerY() , 0 - bounds.centerX()));
endAngle = (float) (180 / Math.PI * Math.atan2(startY - bounds.centerY() , width - bounds.centerX()));
  1. Interpolate between the two angles with this (endAngle-startAngle)*(progress/100f);
  2. Draw the arc and the text

Hope this helps!

Mirco0
  • 306
  • 1
  • 2
  • 8