Android 自定义View之 圆环进度条
程序员文章站
2024-02-06 23:33:46
...
效果图
思路
一共需要画四个圆弧
第一个 最外层的边
第二个 圆环
第三个 内边
第四个 数字所在的边(实现方式 drawTextOnPath)
宽高相等 所以下边会有一点空白 不喜欢可以通过clipChildren 自己去掉 或者用什么布局盖住
本demo 宽度为屏幕的3/5 高度等宽。
代码
package com.power;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
/**
* Created by 于德海 on 2018/8/15.
* package inter.baisong.widgets
* email : aaa@qq.com
*
* @describe
*/
public class PowerView extends View {
private Paint mLine_Paint,mOval_Paint_Grey,mOva_Paint_Blue,mLine_Paint_White,mTextPaint;
private final int DefaultColor = Color.parseColor("#eeeeee");//默认色彩
private final int[] colors = new int[]{Color.parseColor("#4de4f6"),
Color.parseColor("#337fdd"),Color.parseColor("#3347dd")};
private int dip_1,dip_18;
private LinearGradient mLinearGradient;//渐变色
private int mCircle_angle= 240;//内环总度数 180 +60
private final float MAX_POWER =100;//最大算力
private int nowPower;//当前数值
private int needEndPower;//终点数值
private Path [] mPath;//文字的path
private TextView tv_value;
private Context mContext;
private int margin_circle_1,margin_circle_2,margin_circle_3;//圆环环距离外部的边距
public PowerView(Context context) {
this(context,null);
}
public PowerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public void setPower(int power, @NonNull TextView tv_value){
this.tv_value = tv_value;
if(power==0||power==needEndPower)
return;
needEndPower = power;
invalidate();
}
public PowerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
nowPower = 0;
mContext = context;
dip_1 = DisplayUtils.dip2px(context,1);//线宽度
dip_18 = DisplayUtils.dip2px(context,18);//圆环宽度
mLine_Paint= new Paint();
mLine_Paint.setColor(DefaultColor);
mLine_Paint.setStyle(Paint.Style.STROKE);
mLine_Paint.setAntiAlias(true);
mLine_Paint.setStrokeWidth(dip_1);
mLine_Paint_White= new Paint();
mLine_Paint_White.setColor(Color.WHITE);
mLine_Paint_White.setStyle(Paint.Style.STROKE);
mLine_Paint_White.setStrokeWidth(dip_18);
//背景环
mOval_Paint_Grey = new Paint();
mOval_Paint_Grey.setColor(DefaultColor);
mOval_Paint_Grey.setStyle(Paint.Style.STROKE);
mOval_Paint_Grey.setStrokeWidth(dip_18);
mOval_Paint_Grey.setStrokeCap(Paint.Cap.ROUND);
mOval_Paint_Grey.setAntiAlias(true);
//渐变环
mOva_Paint_Blue = new Paint();
mOva_Paint_Blue.setColor(colors[0]);
mOva_Paint_Blue.setStyle(Paint.Style.STROKE);
mOva_Paint_Blue.setAntiAlias(true);
mOva_Paint_Blue.setStrokeCap(Paint.Cap.ROUND);
mOva_Paint_Blue.setStrokeWidth(dip_18);
//字体
mTextPaint = new TextPaint();
mTextPaint.setTextSize(DisplayUtils.sp2px(context,12));
mTextPaint.setColor(Color.parseColor("#a7a7a7"));
mTextPaint.setAntiAlias(true);
margin_circle_1 = DisplayUtils.dip2px(context,20);
margin_circle_2 = DisplayUtils.dip2px(context,35);
margin_circle_3 = DisplayUtils.dip2px(context,50);
}
private RectF rect_1,rect_2,rect_3;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(rect_1==null)
rect_1 = new RectF(dip_1/2,dip_1/2,getWidth()-dip_1/2,getHeight()-dip_1/2);
if(rect_2==null){
rect_2 = new RectF(margin_circle_1,margin_circle_1,getWidth()-margin_circle_1,getHeight()-margin_circle_1);
mLinearGradient = new LinearGradient(margin_circle_1,margin_circle_1,getWidth()-margin_circle_1,margin_circle_1,colors,null,LinearGradient.TileMode.CLAMP);
mOva_Paint_Blue.setShader(mLinearGradient);
}
if(rect_3==null)
rect_3 = new RectF(margin_circle_2,margin_circle_2,getWidth()-margin_circle_2,getHeight()-margin_circle_2);
//绘制圆环相关
canvas.drawArc(rect_1,160,70,false,mLine_Paint);
canvas.drawArc(rect_1,310,70,false,mLine_Paint);
canvas.drawArc(rect_2,150,mCircle_angle,false,mOval_Paint_Grey);
canvas.drawArc(rect_2,150,mCircle_angle*(nowPower/MAX_POWER),false,mOva_Paint_Blue);
canvas.drawArc(rect_3,160,230,false,mLine_Paint);
//绘制白线
drawWhiteLine(canvas);
//绘制文字
drawText(canvas);
if(tv_value!=null){
tv_value.setText(nowPower+"");
}
if(nowPower<needEndPower){
Log.e("text",nowPower+"");
nowPower++;
invalidate();
}else if(nowPower>needEndPower){
nowPower--;
invalidate();
}else if(nowPower==100){
needEndPower = 60;
invalidate();
}
}
private String strs[] = new String[]{"·","20","·","40","·","60","·","80","·"};
private RectF rect_4;
private void drawText(Canvas canvas) {
if(rect_4==null){
rect_4 = new RectF(margin_circle_3,margin_circle_3,getWidth()-margin_circle_3,getWidth()-margin_circle_3);
}
if(mPath==null){
mPath = new Path[9];
for(int i=0;i<9;i++){
mPath[i] = new Path();
if(i%2==1){
mPath[i].addArc(rect_4,150+mCircle_angle/10*(i+1)-4,mCircle_angle/10);
}else if(i==0){
mPath[i].addArc(rect_4,150+mCircle_angle/10*(i+1)-2,mCircle_angle/10);
}else if(i==8){
mPath[i].addArc(rect_4,150+mCircle_angle/10*(i+1)+2,mCircle_angle/10);
}else {
mPath[i].addArc(rect_4,150+mCircle_angle/10*(i+1),mCircle_angle/10);
}
}
}
for(int i=0;i<mPath.length;i++){
canvas.drawTextOnPath(strs[i],mPath[i],0,0,mTextPaint);
}
}
private void drawWhiteLine(Canvas canvas){
canvas.drawArc(rect_2,150+mCircle_angle/5,1,false,mLine_Paint_White);
canvas.drawArc(rect_2,150+mCircle_angle/5*2,1,false,mLine_Paint_White);
canvas.drawArc(rect_2,150+mCircle_angle/5*3,1,false,mLine_Paint_White);
canvas.drawArc(rect_2,150+mCircle_angle/5*4,1,false,mLine_Paint_White);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = DisplayUtils.getWindow_Width((Activity) mContext)/5*3;
setMeasuredDimension(width,width);
}
}
因自己需要 所以就没抽字段 到attr文件里 而且这种东西感觉每个公司跟每个公司的都不一样 所以抽出来意义不大
关键属性都有注释 不懂的可留言询问 发邮件亦可
源码
git地址: 圆环进度条
地址:https://github.com/yudehai0204/Power/
此致 敬礼 !!!