2020-02-12
github地址:https://github.com/gggjmhjmh/OldWangDiy
效果:
B.png
C.png
C.png
功能:
1、可設(shè)置進度條底色、進度值的顏色,文字顏色
2谷扣、可動畫設(shè)置進度值,就是設(shè)置進度值時可以有動畫
3捎琐、可定義陰影:陰影的模糊半徑会涎、偏移和顏色
4、設(shè)置彩色進度值
知識點:
1野哭、通過canvas畫文字在塔、畫圓、畫弧形
2拨黔、根據(jù)控件畫圓的大谢桌!(控件多大,圓就畫多大)
3篱蝇、畫筆Paint設(shè)置陰影贺待;陰影所占的寬度對繪制的影響的處理
4、給Paint設(shè)置著色器(實現(xiàn)漸變)零截,以及著色的起始位置的旋轉(zhuǎn)
代碼:
package com.app.yf.myapplication.view.activity.diy;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
public class MyCircleProgessView extends View {
private static final String TAG = "MyView";
private Context context;
//圓的大小 , 控件的寬麸塞、高 , 誰小取誰的值
private int circleSize;
//進度值 百分比
private float progress = 58;
//線的寬度 px
private int strokeWidth = 30;
private int textSize = 42; //文字大小
private int textColor = Color.BLUE; //文字顏色
private int circleColor = Color.GRAY; //圓的顏色
private int progessColor = Color.GREEN; //進度顏色
private int[] progessColors; //進度值的漸變顏色
private boolean isRound = true; //端點是否為圓頭
/**
* 設(shè)置端點是否為圓頭
*
* @param isRound
*/
public void setIsRound(boolean isRound) {
this.isRound = isRound;
}
/**
* 設(shè)置文字大小 dp
*
* @param textSize
*/
public void setTextSize(int textSize) {
this.textSize = dip2px(context, textSize);
}
public void setTextColor(int textColor) {
setColor(textColor, circleColor, progessColor);
}
public void setCircleColor(int circleColor) {
setColor(textColor, circleColor, progessColor);
}
public void setProgessColor(int progessColor) {
setColor(textColor, circleColor, progessColor);
}
public void setColor(int textColor, int circleColor, int progessColor) {
this.textColor = textColor;
this.circleColor = circleColor;
this.progessColor = progessColor;
// invalidate();
}
/**
* 設(shè)置進度值漸變顏色
*
* @param progessColors 顏色數(shù)組
* @param isRound 端點是否為圓頭, 注:為圓頭時涧衙,起點的圓頭是結(jié)尾的顏色哪工。開始和結(jié)束的顏色設(shè)為一樣的就沒問題
*/
public void setProgessColor(int[] progessColors, boolean isRound) {
this.progessColors = progessColors;
this.isRound = isRound;
}
/**
* 設(shè)置線的寬度
*
* @param strokeWidth dp
*/
public void setStrokeWidth(int strokeWidth) {
this.strokeWidth = dip2px(context, strokeWidth);
}
private int shadowWidth = 15; //陰影一邊所占的寬度 px
/**
* 設(shè)置陰影
*
* @param radius 陰影模糊半徑 dp
* @param dx 偏移x dp
* @param dy 偏移y dp
* @param shadowColor 陰影顏色
*/
public void setShadow(float radius, float dx, float dy, int shadowColor) {
drawCirclePaint.setShadowLayer(dip2px(context, radius), dip2px(context, dx), dip2px(context, dy), shadowColor);
//陰影所一邊所占的寬度 = 模糊半徑 + 模糊半徑/2 + x與y的偏移最大值
shadowWidth = dip2px(context, radius + radius / 2 + Math.max(dx, dy));
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
invalidate();
}
/**
* 動畫效果設(shè)置進度值
*
* @param progress 進度值
* @param duration 動畫時間
*/
public void setProgressAnimation(float progress, long duration) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress", 0, progress);
objectAnimator.setDuration(duration);
objectAnimator.start();
}
public MyCircleProgessView(Context context) {
super(context);
init(context);
}
public MyCircleProgessView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
this.context = context;
setStrokeWidth(10); //設(shè)置默認為10dp
// 初始化畫筆
initPaint();
}
private Paint mPaint; //畫文字及進度值的畫筆
private Paint drawCirclePaint; //畫底部圓的畫筆,之所以要再弄個畫筆弧哎,是為了方便設(shè)置陰影
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Paint.Align.CENTER); //對齊方式: 左中右
drawCirclePaint = new Paint();
drawCirclePaint.setAntiAlias(true);
drawCirclePaint.setStyle(Paint.Style.STROKE); //設(shè)置空心
drawCirclePaint.setStrokeWidth(strokeWidth); //設(shè)置筆畫寬度
drawCirclePaint.setColor(circleColor); //設(shè)置顏色
setShadow(2, 1, 2, Color.RED); //設(shè)置陰影
}
/**
* 根據(jù)手機的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.i(TAG, "onMeasure: width: " + widthMeasureSpec);
Log.i(TAG, "onMeasure: height: " + heightMeasureSpec);
Log.i(TAG, "onMeasure: getWidth: " + getWidth());
Log.i(TAG, "onMeasure: getheight: " + getHeight());
Log.i(TAG, "onMeasure: getMeasuredWidth: " + getMeasuredWidth());
Log.i(TAG, "onMeasure: getMeasuredHeight: " + getMeasuredHeight());
//圓的大小 , 控件的寬雁比、高 , 誰小取誰的值
circleSize = Math.min(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
// canvas.drawColor(Color.RED);
//畫文字
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(textColor);
mPaint.setTextSize(textSize);
float y = mPaint.getFontSpacing() / 3; //行距:第一行的基線與第二行的基線的距離
canvas.drawText((int) progress + "%", circleSize / 2, circleSize / 2 + y, mPaint);
//畫進度條底部圓
canvas.drawCircle(circleSize / 2, circleSize / 2, circleSize / 2 - strokeWidth / 2 - shadowWidth, drawCirclePaint);
/* - strokeWidth / 2 畫的線為內(nèi)邊距效果,不然一半的線寬就越出范圍了 */
mPaint.setStyle(Paint.Style.STROKE); //設(shè)置空心
mPaint.setStrokeWidth(strokeWidth); //設(shè)置筆畫寬度
mPaint.setColor(progessColor);
//如果設(shè)置了漸變
if (progessColors != null) {
//設(shè)置著色器撤嫩,畫漸變
Shader sweepGradient = new SweepGradient(circleSize / 2f, circleSize / 2f, progessColors, null);
//設(shè)置起始位置旋轉(zhuǎn)90度
Matrix matrix = new Matrix();
matrix.setRotate(90, circleSize / 2, circleSize / 2);
sweepGradient.setLocalMatrix(matrix);
mPaint.setShader(sweepGradient);
}
//設(shè)置端點是否為圓頭
mPaint.setStrokeCap(isRound ? Paint.Cap.ROUND : Paint.Cap.BUTT);
//畫進度條的進度值弧線偎捎。 線的寬度/2 為超出本身大小的寬度(因為畫的線不是內(nèi)、外邊距序攘,而是居中) 再加上陰影要占用的寬度
canvas.drawArc(strokeWidth / 2 + shadowWidth, strokeWidth / 2 + shadowWidth, circleSize - strokeWidth / 2 - shadowWidth, circleSize - strokeWidth / 2 - shadowWidth, 90, progress * 3.6f, false, mPaint);
mPaint.setShader(null); //清除著色器
canvas.restore();
}
}
使用:
MyCircleProgessView myView = findViewById(R.id.myView);
myView.setShadow(5, 0, 0, Color.RED); // 設(shè)置陰影
//設(shè)置彩色進度值
myView.setProgessColor(new int[]{Color.GREEN, Color.BLUE, Color.RED, Color.GREEN}, true);
//動畫效果設(shè)置進度值
myView .setProgressAnimation(90,800);
github地址:https://github.com/gggjmhjmh/OldWangDiy
完事兒