一、前言:
最近公司有个需求,需要自定义圆环的颜色和进度,效果图如下:
1、创建类,继承view,重写onDraw和onMesure方法
public class CirclePercentBar extends View {
private Context mContext;
private int mArcColor;
private int mArcWidth;
private int mCenterTextColor;
private int mCenterTextSize;
private int mCircleRadius;
private Paint arcPaint;
private Paint arcCirclePaint;
private Paint centerTextPaint;
private RectF arcRectF;
private Rect textBoundRect;
private float mCurData=0;
private int arcStartColor;
private int arcEndColor;
private Paint startCirclePaint;
public CirclePercentBar(Context context) {
this(context, null);
}
public CirclePercentBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CirclePercentBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext=context;
//color_FFEBEEF5
TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.CirclePercentBar,defStyleAttr,0);
mArcColor = typedArray.getColor(R.styleable.CirclePercentBar_arcColor,0xff0000);
mArcWidth = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_arcWidth, DisplayUtil.dp2px(context, 20));
mCenterTextColor = typedArray.getColor(R.styleable.CirclePercentBar_centerTextColor, 0x0000ff);
mCenterTextSize = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_centerTextSize, DisplayUtil.dp2px(context, 20));
mCircleRadius = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_circleRadius, DisplayUtil.dp2px(context, 100));
arcStartColor = typedArray.getColor(R.styleable.CirclePercentBar_arcStartColor,
ContextCompat.getColor(mContext, R.color.color_FFF9612D));
arcEndColor = typedArray.getColor(R.styleable.CirclePercentBar_arcEndColor,
ContextCompat.getColor(mContext, R.color.color_FF58C89E));
typedArray.recycle();
initPaint();
}
private void initPaint() {
startCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
startCirclePaint.setStyle(Paint.Style.FILL);
//startCirclePaint.setStrokeWidth(mArcWidth);
startCirclePaint.setColor(arcStartColor);
arcCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
arcCirclePaint.setStyle(Paint.Style.STROKE);
arcCirclePaint.setStrokeWidth(mArcWidth);
//底部默认的圆环色 color_FFF96857 color_FFEBEEF5
arcCirclePaint.setColor(ContextCompat.getColor(mContext,R.color.color_FFF96857));
arcCirclePaint.setStrokeCap(Paint.Cap.ROUND);
arcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
arcPaint.setStyle(Paint.Style.STROKE);
arcPaint.setStrokeWidth(mArcWidth);
arcPaint.setColor(mArcColor);
arcPaint.setStrokeCap(Paint.Cap.ROUND);
centerTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
centerTextPaint.setStyle(Paint.Style.STROKE);
centerTextPaint.setColor(mCenterTextColor);
centerTextPaint.setTextSize(mCenterTextSize);
//圓弧的外接矩形
arcRectF = new RectF();
//文字的边界矩形
textBoundRect = new Rect();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureDimension(widthMeasureSpec),measureDimension(heightMeasureSpec));
}
private int measureDimension(int measureSpec) {
int result;
int specMode=MeasureSpec.getMode(measureSpec);
int specSize=MeasureSpec.getSize(measureSpec);
if(specMode==MeasureSpec.EXACTLY){
result=specSize;
}else{
result=mCircleRadius*2;
if(specMode==MeasureSpec.AT_MOST){
result=Math.min(result,specSize);
}
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.rotate(-90, getWidth()/ 2, getHeight()/ 2);
arcRectF.set(getWidth()/2-mCircleRadius+mArcWidth/2,getHeight()/2-mCircleRadius+mArcWidth/2
,getWidth()/2+mCircleRadius-mArcWidth/2,getHeight()/2+mCircleRadius-mArcWidth/2);
canvas.drawArc(arcRectF, 0,360,false,arcCirclePaint);
arcPaint.setShader(new SweepGradient(getWidth()/2,getHeight()/2,arcStartColor,arcEndColor));
canvas.drawArc(arcRectF, 0,360* mCurData /100,false,arcPaint);
canvas.rotate(90, getWidth()/ 2, getHeight()/ 2);
canvas.drawCircle(getWidth()/2,getHeight()/2-mCircleRadius+mArcWidth/2,mArcWidth/2,startCirclePaint);
String data= String.valueOf(mCurData) +"%";
centerTextPaint.getTextBounds(data,0,data.length(),textBoundRect);
canvas.drawText(data,getWidth()/2-textBoundRect.width()/2,getHeight()/2+textBoundRect.height()/2,centerTextPaint);
}
public void setPercentData(float data, TimeInterpolator interpolator){
ValueAnimator valueAnimator=ValueAnimator.ofFloat(mCurData,data);
valueAnimator.setDuration((long) (Math.abs(mCurData-data)*30));
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float value= (float) valueAnimator.getAnimatedValue();
mCurData=(float)(Math.round(value*10))/10;
invalidate();
}
});
valueAnimator.setInterpolator(interpolator);
valueAnimator.start();
}
}
2、其中需要用到的类
public class DisplayUtil {
public static int px2dp(Context context,float pxValue){
final float scale=context.getResources().getDisplayMetrics().density;
return (int)(pxValue/scale+0.5f);
}
public static int dp2px(Context context,float dpValue){
final float scale=context.getResources().getDisplayMetrics().density;
return (int)(dpValue*scale+0.5f);
}
}
3、attrs.xml
4、在activity_main里面写布局
5、编程实现效果:
public class MainActivity extends AppCompatActivity {
CirclePercentBar circlePercentBar;
Button startBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circlePercentBar= (CirclePercentBar) findViewById(R.id.circle_bar);
circlePercentBar.setPercentData(55.2f,new DecelerateInterpolator());
startBtn= (Button) findViewById(R.id.start_btn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
circlePercentBar.setPercentData((float) (100*Math.random()),new DecelerateInterpolator());
}
});
}
}
参考链接:https://www.jb51.net/article/144732.htm
- https://www.jb51.net/article/104068.htm