基於項目ColorArcProgressBar自己改了點東西,去項目原地址
先看效果圖:
圓弧線條可以設置漸變色。
下面上代碼,需要什麼需求自己改咯
首先是xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="gy.net.named.MainActivity"> <gy.net.named.view.ColorArcProgressBar android:id="@+id/myProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="150px" android:layout_marginTop="50px" app:is_need_content="true" app:front_color1="#FFC62C" app:front_color2="#FF2EAB" app:front_color3="#BB0839" app:back_width="2dp" app:front_width="10dp" app:max_value="100" app:total_engle="270" app:back_color="@android:color/darker_gray" /> <gy.net.named.RaiseNumberAnimTextView android:id="@+id/souce" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="230px" android:text="" android:textColor="#c24e4e" android:textSize="138px" android:textStyle="bold" /> </LinearLayout>
然後是自定義控件
public class ColorArcProgressBar extends View { private int mWidth; private int mHeight; private int diameter = 500; //直徑 private float centerX; //圓心X座標 private float centerY; //圓心Y座標 private Paint allArcPaint; private Paint progressPaint; private Paint vTextPaint; private Paint hintPaint; private Paint degreePaint; private Paint curSpeedPaint; private RectF bgRect; private ValueAnimator progressAnimator; private PaintFlagsDrawFilter mDrawFilter; private SweepGradient sweepGradient; private Matrix rotateMatrix; private float startAngle = 135; private float sweepAngle = 270; private float currentAngle = 0; private float lastAngle; private int[] colors = new int[]{Color.GREEN, Color.YELLOW, Color.RED, Color.RED}; private float maxValues = 60; private float curValues = 0; private float bgArcWidth = dipToPx(2); private float progressWidth = dipToPx(10); private float textSize = dipToPx(60); private float hintSize = dipToPx(15); private float curSpeedSize = dipToPx(13); private int aniSpeed = 1000; private float longdegree = dipToPx(13); private float shortdegree = dipToPx(5); private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8); private Path mPath; private String hintColor = "#676767"; private String longDegreeColor = "#111111"; private String shortDegreeColor = "#111111"; private String bgArcColor = "#111111"; private String titleString; private String hintString; private boolean isShowCurrentSpeed = true; private boolean isNeedTitle; private boolean isNeedUnit; private boolean isNeedDial; private boolean isNeedContent; // sweepAngle / maxValues 的值 private float k; private DashPathEffect dashPathEffect; private SweepGradient mColorShader; public ColorArcProgressBar(Context context) { super(context, null); initView(); } public ColorArcProgressBar(Context context, AttributeSet attrs) { super(context, attrs, 0); initCofig(context, attrs); initView(); } public ColorArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initCofig(context, attrs); initView(); } /** * 初始化佈局配置 * @param context * @param attrs */ private void initCofig(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorArcProgressBar); int color1 = a.getColor(R.styleable.ColorArcProgressBar_front_color1, Color.GREEN); int color2 = a.getColor(R.styleable.ColorArcProgressBar_front_color2, color1); int color3 = a.getColor(R.styleable.ColorArcProgressBar_front_color3, color1); colors = new int[]{color1, color2, color3, color3}; sweepAngle = a.getInteger(R.styleable.ColorArcProgressBar_total_engle, 270); bgArcWidth = a.getDimension(R.styleable.ColorArcProgressBar_back_width, dipToPx(2)); progressWidth = a.getDimension(R.styleable.ColorArcProgressBar_front_width, dipToPx(10)); isNeedTitle = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_title, false); isNeedContent = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_content, false); isNeedUnit = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_unit, false); isNeedDial = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_dial, false); hintString = a.getString(R.styleable.ColorArcProgressBar_string_unit); titleString = a.getString(R.styleable.ColorArcProgressBar_string_title); curValues = a.getFloat(R.styleable.ColorArcProgressBar_current_value, 0); maxValues = a.getFloat(R.styleable.ColorArcProgressBar_max_value, 60); mPath = new Path(); setCurrentValues(curValues); setMaxValues(maxValues); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE); int height= (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE); setMeasuredDimension(width, height); } private void initView() { diameter = 2 * getScreenWidth() / 5 +getScreenWidth()/15; //弧形的矩陣區域 bgRect = new RectF(); bgRect.top = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE; bgRect.left = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE; bgRect.right = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE); bgRect.bottom = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE); //圓心 centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2; centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2; //外部刻度線 degreePaint = new Paint(); degreePaint.setColor(Color.parseColor(longDegreeColor)); //整個弧形 allArcPaint = new Paint(); allArcPaint.setAntiAlias(true); allArcPaint.setStyle(Paint.Style.STROKE); allArcPaint.setStrokeWidth(bgArcWidth); allArcPaint.setColor(Color.parseColor(bgArcColor)); allArcPaint.setStrokeCap(Paint.Cap.ROUND); //當前進度的弧形 progressPaint = new Paint(); progressPaint.setAntiAlias(true); progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeWidth(progressWidth); progressPaint.setColor(Color.GREEN); //內容顯示文字 vTextPaint = new Paint(); vTextPaint.setTextSize(textSize); vTextPaint.setColor(Color.BLACK); vTextPaint.setTextAlign(Paint.Align.CENTER); //顯示單位文字 hintPaint = new Paint(); hintPaint.setTextSize(hintSize); hintPaint.setColor(Color.parseColor(hintColor)); hintPaint.setTextAlign(Paint.Align.CENTER); //顯示標題文字 curSpeedPaint = new Paint(); curSpeedPaint.setTextSize(curSpeedSize); curSpeedPaint.setColor(Color.parseColor(hintColor)); curSpeedPaint.setTextAlign(Paint.Align.CENTER); mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); sweepGradient = new SweepGradient(centerX, centerY, colors, null); rotateMatrix = new Matrix(); } @Override protected void onDraw(Canvas canvas) { //抗鋸齒 canvas.setDrawFilter(mDrawFilter); if (isNeedDial) { //畫刻度線 for (int i = 0; i < 40; i++) { if (i > 15 && i < 25) { canvas.rotate(9, centerX, centerY); continue; } if (i % 5 == 0) { degreePaint.setStrokeWidth(dipToPx(2)); degreePaint.setColor(Color.parseColor(longDegreeColor)); canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE, centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - longdegree, degreePaint); } else { degreePaint.setStrokeWidth(dipToPx(1.4f)); degreePaint.setColor(Color.parseColor(shortDegreeColor)); canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2, centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2 - shortdegree, degreePaint); } canvas.rotate(9, centerX, centerY); } } //整個弧 // canvas.drawArc(bgRect, startAngle, sweepAngle, false, allArcPaint); //設置漸變色 rotateMatrix.setRotate(130, centerX, centerY); sweepGradient.setLocalMatrix(rotateMatrix); progressPaint.setShader(sweepGradient); progressPaint.setPathEffect(new DashPathEffect(new float[] {5,15}, 0)); //當前進度 canvas.drawArc(bgRect, startAngle, currentAngle, false, progressPaint); invalidate(); } /** * 設置最大值 * @param maxValues */ public void setMaxValues(float maxValues) { this.maxValues = maxValues; k = sweepAngle/maxValues; } /** * 設置當前值 * @param currentValues */ public void setCurrentValues(float currentValues) { if (currentValues > maxValues) { currentValues = maxValues; } if (currentValues < 0) { currentValues = 0; } this.curValues = currentValues; lastAngle = currentAngle; setAnimation(lastAngle, currentValues * k, aniSpeed); } /** * 設置整個圓弧寬度 * @param bgArcWidth */ public void setBgArcWidth(int bgArcWidth) { this.bgArcWidth = bgArcWidth; } /** * 設置進度寬度 * @param progressWidth */ public void setProgressWidth(int progressWidth) { this.progressWidth = progressWidth; } /** * 設置速度文字大小 * @param textSize */ public void setTextSize(int textSize) { this.textSize = textSize; } /** * 設置單位文字大小 * @param hintSize */ public void setHintSize(int hintSize) { this.hintSize = hintSize; } /** * 設置單位文字 * @param hintString */ public void setUnit(String hintString) { this.hintString = hintString; invalidate(); } /** * 設置直徑大小 * @param diameter */ public void setDiameter(int diameter) { this.diameter = dipToPx(diameter); } /** * 設置標題 * @param title */ private void setTitle(String title){ this.titleString = title; } /** * 設置是否顯示標題 * @param isNeedTitle */ private void setIsNeedTitle(boolean isNeedTitle) { this.isNeedTitle = isNeedTitle; } /** * 設置是否顯示單位文字 * @param isNeedUnit */ private void setIsNeedUnit(boolean isNeedUnit) { this.isNeedUnit = isNeedUnit; } /** * 設置是否顯示外部刻度盤 * @param isNeedDial */ private void setIsNeedDial(boolean isNeedDial) { this.isNeedDial = isNeedDial; } /** * 爲進度設置動畫 * @param last * @param current */ private void setAnimation(float last, float current, int length) { progressAnimator = ValueAnimator.ofFloat(last, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngle); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentAngle= (float) animation.getAnimatedValue(); curValues = currentAngle/k; } }); progressAnimator.start(); } /** * dip 轉換成px * @param dip * @return */ private int dipToPx(float dip) { float density = getContext().getResources().getDisplayMetrics().density; return (int)(dip * density + 0.5f * (dip >= 0 ? 1 : -1)); } /** * 得到屏幕寬度 * @return */ private int getScreenWidth() { WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics displayMetrics = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.widthPixels; } }
然後一個數字變化的自定義控件,在網上找的
public class RaiseNumberAnimTextView extends TextView { private long mDuration = 1000; // 動畫持續時間 ms,默認1s private ValueAnimator animator; private TimeInterpolator mTimeInterpolator = new LinearInterpolator(); // 動畫速率 private AnimEndListener mEndListener; // 動畫正常結束監聽事件 public RaiseNumberAnimTextView(Context context) { super(context); } public RaiseNumberAnimTextView(Context context, AttributeSet attrs) { super(context, attrs); } public RaiseNumberAnimTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 設置動畫持續時間,默認爲1s。需要在setNumberWithAnim之前設置纔有效 * @param duration */ public void setDuration(long duration) { if (duration > 0) { mDuration = duration; } } /** * 設置動畫速率,默認爲LinearInterpolator。需要在setNumberWithAnim之前設置纔有效 * @param timeInterpolator */ public void setAnimInterpolator(TimeInterpolator timeInterpolator) { mTimeInterpolator = timeInterpolator; } /** * 設置要顯示的float數字,帶動畫顯示 * @param number */ public void setNumberWithAnim(float number) { clearAnimator(); // 設置動畫,float值的起始值 animator = ValueAnimator.ofFloat(0.0f, number); startAnimator(); } /** * 設置要顯示的int數字,帶動畫顯示。 * @param number */ public void setNumberWithAnim(int number) { clearAnimator(); // 設置動畫,int值的起始值 animator = ValueAnimator.ofInt(0, number); startAnimator(); } // 清除動畫 public void clearAnimator() { if (null != animator) { if (animator.isRunning()) { animator.removeAllListeners(); animator.removeAllUpdateListeners(); animator.cancel(); } animator = null; } } // 暫停動畫 public void onPause() { if (null != animator && animator.isRunning()) { animator.pause(); // API 不低於19 } } // 繼續執行動畫 public void onResume() { if (null != animator && animator.isRunning()) { animator.resume(); } } // 設置時常與過程處理,啓動動畫 private void startAnimator() { if (null != animator) { animator.setDuration(mDuration); animator.setInterpolator(mTimeInterpolator); // 動畫過程中獲取當前值,顯示 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { setText(valueAnimator.getAnimatedValue().toString()); } }); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { if (null != mEndListener) { // 動畫不是中途取消,而是正常結束 mEndListener.onAnimFinish(); } } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); animator.start(); } } public void setAnimEndListener(AnimEndListener listener) { mEndListener = listener; } // 動畫顯示數字的結束監聽,當動畫結束顯示正確的數字時,可能需要做些處理 public interface AnimEndListener { void onAnimFinish(); } }
最後MainActivity使用,很簡單
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ColorArcProgressBar colorArcProgressBar = (ColorArcProgressBar) findViewById(R.id.myProgress); RaiseNumberAnimTextView souce = (RaiseNumberAnimTextView) findViewById(R.id.souce); //數字變化 souce.setNumberWithAnim(900); // double sub = Arith.sub(900, 500); // double num1 = Arith.div(sub, 400, 2); // int num = (int) (num1 * 100); //圓弧的進度條 colorArcProgressBar.setCurrentValues(900); }
記錄一下工作之中學到的東西,怕忘記,寫在博客中。