content: package com.github.lzyzsd.circleprogress;
  
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.RectF;
  import android.os.Bundle;
  import android.os.Parcelable;
  import android.text.TextPaint;
  import android.text.TextUtils;
  import android.util.AttributeSet;
  import android.view.View;
  
  /**
   * Created by bruce on 11/4/14.
   */
  public class CircleProgress extends View {
      private Paint textPaint;
      private RectF rectF = new RectF();
  
      private float textSize;
      private int textColor;
      private int progress = 0;
      private int max;
      private int finishedColor;
      private int unfinishedColor;
      private String prefixText = "";
      private String suffixText = "%";
  
      private final int default_finished_color = Color.rgb(66, 145, 241);
      private final int default_unfinished_color = Color.rgb(204, 204, 204);
      private final int default_text_color = Color.WHITE;
      private final int default_max = 100;
      private final float default_text_size;
      private final int min_size;
  
      private static final String INSTANCE_STATE = "saved_instance";
      private static final String INSTANCE_TEXT_COLOR = "text_color";
      private static final String INSTANCE_TEXT_SIZE = "text_size";
      private static final String INSTANCE_FINISHED_STROKE_COLOR = "finished_stroke_color";
      private static final String INSTANCE_UNFINISHED_STROKE_COLOR = "unfinished_stroke_color";
      private static final String INSTANCE_MAX = "max";
      private static final String INSTANCE_PROGRESS = "progress";
      private static final String INSTANCE_SUFFIX = "suffix";
      private static final String INSTANCE_PREFIX = "prefix";
  
      private Paint paint = new Paint();
  
      public CircleProgress(Context context) {
          this(context, null);
      }
  
      public CircleProgress(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
  
          default_text_size = Utils.sp2px(getResources(), 18);
          min_size = (int) Utils.dp2px(getResources(), 100);
  
          final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgress, defStyleAttr, 0);
          initByAttributes(attributes);
          attributes.recycle();
  
          initPainters();
      }
  
      protected void initByAttributes(TypedArray attributes) {
          finishedColor = attributes.getColor(R.styleable.CircleProgress_circle_finished_color, default_finished_color);
          unfinishedColor = attributes.getColor(R.styleable.CircleProgress_circle_unfinished_color, default_unfinished_color);
          textColor = attributes.getColor(R.styleable.CircleProgress_circle_text_color, default_text_color);
          textSize = attributes.getDimension(R.styleable.CircleProgress_circle_text_size, default_text_size);
  
          setMax(attributes.getInt(R.styleable.CircleProgress_circle_max, default_max));
          setProgress(attributes.getInt(R.styleable.CircleProgress_circle_progress, 0));
  
          if (attributes.getString(R.styleable.CircleProgress_circle_prefix_text) != null) {
              setPrefixText(attributes.getString(R.styleable.CircleProgress_circle_prefix_text));
          }
          if (attributes.getString(R.styleable.CircleProgress_circle_suffix_text) != null) {
              setSuffixText(attributes.getString(R.styleable.CircleProgress_circle_suffix_text));
          }
      }
  
      protected void initPainters() {
          textPaint = new TextPaint();
          textPaint.setColor(textColor);
          textPaint.setTextSize(textSize);
          textPaint.setAntiAlias(true);
  
          paint.setAntiAlias(true);
      }
  
      @Override
      public void invalidate() {
          initPainters();
          super.invalidate();
      }
  
      public int getProgress() {
          return progress;
      }
  
      public void setProgress(int progress) {
          this.progress = progress;
          if (this.progress > getMax()) {
              this.progress %= getMax();
          }
          invalidate();
      }
  
      public int getMax() {
          return max;
      }
  
      public void setMax(int max) {
          if (max > 0) {
              this.max = max;
              invalidate();
          }
      }
  
      public float getTextSize() {
          return textSize;
      }
  
      public void setTextSize(float textSize) {
          this.textSize = textSize;
          this.invalidate();
      }
  
      public int getTextColor() {
          return textColor;
      }
  
      public void setTextColor(int textColor) {
          this.textColor = textColor;
          this.invalidate();
      }
  
      public int getFinishedColor() {
          return finishedColor;
      }
  
      public void setFinishedColor(int finishedColor) {
          this.finishedColor = finishedColor;
          this.invalidate();
      }
  
      public int getUnfinishedColor() {
          return unfinishedColor;
      }
  
      public void setUnfinishedColor(int unfinishedColor) {
          this.unfinishedColor = unfinishedColor;
          this.invalidate();
      }
  
      public String getPrefixText() {
          return prefixText;
      }
  
      public void setPrefixText(String prefixText) {
          this.prefixText = prefixText;
          this.invalidate();
      }
  
      public String getSuffixText() {
          return suffixText;
      }
  
      public void setSuffixText(String suffixText) {
          this.suffixText = suffixText;
          this.invalidate();
      }
  
      public String getDrawText() {
          return getPrefixText() + getProgress() + getSuffixText();
      }
  
      @Override
      protected int getSuggestedMinimumHeight() {
          return min_size;
      }
  
      @Override
      protected int getSuggestedMinimumWidth() {
          return min_size;
      }
  
      public float getProgressPercentage() {
          return getProgress() / (float) getMax();
      }
  
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          rectF.set(0, 0, MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
          setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
      }
  
      @Override protected void onDraw(Canvas canvas) {
          float yHeight = getProgress() / (float) getMax() * getHeight();
          float radius = getWidth() / 2f;
          float angle = (float) (Math.acos((radius - yHeight) / radius) * 180 / Math.PI);
          float startAngle = 90 + angle;
          float sweepAngle = 360 - angle * 2;
          paint.setColor(getUnfinishedColor());
          canvas.drawArc(rectF, startAngle, sweepAngle, false, paint);
  
          canvas.save();
          canvas.rotate(180, getWidth() / 2, getHeight() / 2);
          paint.setColor(getFinishedColor());
          canvas.drawArc(rectF, 270 - angle, angle * 2, false, paint);
          canvas.restore();
  
          String text = getDrawText();
          if (!TextUtils.isEmpty(text)) {
              float textHeight = textPaint.descent() + textPaint.ascent();
              canvas.drawText(text, (getWidth() - textPaint.measureText(text)) / 2.0f, (getWidth() - textHeight) / 2.0f, textPaint);
          }
      }
  
      @Override
      protected Parcelable onSaveInstanceState() {
          final Bundle bundle = new Bundle();
          bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
          bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
          bundle.putFloat(INSTANCE_TEXT_SIZE, getTextSize());
          bundle.putInt(INSTANCE_FINISHED_STROKE_COLOR, getFinishedColor());
          bundle.putInt(INSTANCE_UNFINISHED_STROKE_COLOR, getUnfinishedColor());
          bundle.putInt(INSTANCE_MAX, getMax());
          bundle.putInt(INSTANCE_PROGRESS, getProgress());
          bundle.putString(INSTANCE_SUFFIX, getSuffixText());
          bundle.putString(INSTANCE_PREFIX, getPrefixText());
          return bundle;
      }
  
      @Override
      protected void onRestoreInstanceState(Parcelable state) {
          if(state instanceof Bundle) {
              final Bundle bundle = (Bundle) state;
              textColor = bundle.getInt(INSTANCE_TEXT_COLOR);
              textSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
              finishedColor = bundle.getInt(INSTANCE_FINISHED_STROKE_COLOR);
              unfinishedColor = bundle.getInt(INSTANCE_UNFINISHED_STROKE_COLOR);
              initPainters();
              setMax(bundle.getInt(INSTANCE_MAX));
              setProgress(bundle.getInt(INSTANCE_PROGRESS));
              prefixText = bundle.getString(INSTANCE_PREFIX);
              suffixText = bundle.getString(INSTANCE_SUFFIX);
              super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
              return;
          }
          super.onRestoreInstanceState(state);
      }
  }
  