此文参考了https://github.com/HotBitmapGG/CreditSesameRingView
感谢作者的分享!!
基础部分就不说了,直接说核心部分,不理解的可以去看
android开发自定义View(一)
android开发自定义View(二)自定义圆形进度条
1.测量控件大小
<cn.jiangzehui.www.myview3.MyView
android:id="@+id/mv"
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
private int radus;//半径
private int defalutSize ;//默认大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
int width,height;
if(wMode == MeasureSpec.EXACTLY){
width = wSize;
}else{
width=Math.min(wSize,defalutSize);
}
if(hMode == MeasureSpec.EXACTLY){
height = hSize;
}else{
height=Math.min(hSize,defalutSize);
}
radus = width/2;
setMeasuredDimension(width,height);
}
/** * dp转px * * @param values * @return */
public int dp_px(int values)
{
float density = getResources().getDisplayMetrics().density;
return (int) (values * density + 0.5f);
}
如果在布局中没有设定指定的大小也就是wrap_content的时候,我们需要给控制设置一个默认值defalutSize。如果不设置控件会默认全屏显示。
首先初始化一下外环画笔,各种属性可根据实际情况微调。
private Paint wPaint;//外环画笔
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
defalutSize = dp_px(defalutSize);
wPaint=new Paint();
wPaint.setAntiAlias(true);
wPaint.setColor(Color.WHITE);
wPaint.setAlpha(50);//透明度,取值范围为0~255,数值越小越透明
wPaint.setStyle(Paint.Style.STROKE);
wPaint.setStrokeWidth(10);
}
绘制
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
final RectF rf=new RectF(getPaddingLeft(),getPaddingTop(),getWidth()-getPaddingRight(),getHeight()-getPaddingBottom());
//绘制外环
canvas.drawArc(rf,-195,210,false,wPaint);//总360
}
声明变量
private Paint nPaint;//内环画笔
private int distance = 30;//外环于内环的间距
在构造方法里初始化画笔
//初始化内环画笔
distance = dp_px(distance);
nPaint=new Paint();
nPaint.setAntiAlias(true);
nPaint.setColor(Color.WHITE);
nPaint.setAlpha(50);
nPaint.setStyle(Paint.Style.STROKE);
nPaint.setStrokeWidth(30);
绘制
RectF n_rf=new RectF(getPaddingLeft()+distance,getPaddingTop()+distance,getWidth()-(getPaddingRight()+distance),getHeight()-(getPaddingBottom()+distance));
//绘制内环
canvas.drawArc(n_rf,-195,210,false,nPaint);
声明变量
private Paint nk_Paint;//内层小刻度画笔
private Paint lfPaint;//内层大刻度画笔
初始化
nk_Paint=new Paint();
nk_Paint.setAntiAlias(true);
nk_Paint.setColor(Color.WHITE);
nk_Paint.setAlpha(80);
lfPaint=new Paint();
lfPaint.setAntiAlias(true);
lfPaint.setStrokeWidth(2);
lfPaint.setColor(Color.WHITE);
lfPaint.setAlpha(100);
绘制
//绘制内环刻度
canvas.save();
canvas.rotate(-105, radus, radus);
//计算刻度线的起点结束点
int startDst = (int) (getPaddingLeft()+distance - nPaint.getStrokeWidth() / 2 );
int endDst = (int) (startDst + nPaint.getStrokeWidth());
int endDsts = (int) (startDst + nPaint.getStrokeWidth()+5);
for (int i = 1; i <= 31; i++)
{
//每旋转4度绘制一个小刻度
canvas.drawLine(radus, startDst, radus, endDst, nk_Paint);
canvas.rotate(7, radus, radus);
}
canvas.restore();
canvas.save();
canvas.rotate(-105, radus, radus);
for (int i = 1; i <= 6; i++)
{
//每旋转4度绘制一个小刻度
canvas.drawLine(radus, startDst, radus, endDsts, lfPaint);
canvas.rotate(42, radus, radus);
}
canvas.restore();
声明变量
String[] str ={"350","较差","550","中等","600","良好","650","优秀","700","极好","950"};
private Paint ztPaint;//刻度等级字体画笔
private Paint btPaint;//BETA画笔
private Paint szPaint;//675画笔
private Paint djPaint;//信用等级画笔
private Paint pgPaint;//评估时间画笔
// 最小数字
private int mMinNum = 350;
// 最大数字
private int mMaxNum = 950;
//信用等级
private String sesameLevel = "";
//总进度
private float mTotalAngle = 210f;
//评估时间
private String evaluationTime = "";
初始化
ztPaint=new Paint();
ztPaint.setAntiAlias(true);
ztPaint.setColor(Color.WHITE);
ztPaint.setTextSize(25);
ztPaint.setAlpha(100);
btPaint=new Paint();
btPaint.setAntiAlias(true);
btPaint.setColor(Color.WHITE);
btPaint.setTextSize(30);
btPaint.setAlpha(100);
szPaint=new Paint();
szPaint.setAntiAlias(true);
szPaint.setColor(Color.WHITE);
szPaint.setTextSize(140);
djPaint=new Paint();
djPaint.setAntiAlias(true);
djPaint.setColor(Color.WHITE);
djPaint.setTextSize(65);
pgPaint=new Paint();
pgPaint.setAntiAlias(true);
pgPaint.setColor(Color.WHITE);
pgPaint.setTextSize(30);
pgPaint.setAlpha(100);
绘制
//绘制内环各刻度等级
canvas.save();
canvas.rotate(-105, radus, radus);
//计算刻度线的起点结束点
for (int i = 0; i < str.length; i++)
{
//每旋转4度绘制一个小刻度
float textLen = ztPaint.measureText(str[i]);
canvas.drawText(str[i],radus - textLen / 2,endDst + 40,ztPaint);
canvas.rotate(21, radus, radus);
}
canvas.restore();
//绘制BEAT文字
Rect rt=new Rect();
btPaint.getTextBounds("BETA",0,"BETA".length(),rt);
float beta_hight = rt.height();
float beta_width = rt.width();
canvas.drawText("BETA",radus - beta_width / 2,radus/2,btPaint);
//绘制信用等级
Rect rt1=new Rect();
if(mMinNum!=0){
szPaint.getTextBounds("111",0,"111".length(),rt1);
float textLen1 = szPaint.measureText(mMinNum+"");
canvas.drawText(mMinNum+"",radus - textLen1 / 2,radus/2+beta_hight+rt1.height(),szPaint);
}
//绘制信用级别
Rect rt2=new Rect();
djPaint.getTextBounds(sesameLevel,0,sesameLevel.length(),rt2);
float textLen2 = djPaint.measureText(sesameLevel);
canvas.drawText(sesameLevel,radus - textLen2 / 2,radus/2+beta_hight*2+rt2.height()+rt1.height(),djPaint);
//绘制评估时间
Rect rt3=new Rect();
pgPaint.getTextBounds(evaluationTime,0,evaluationTime.length(),rt3);
float textLen3 = pgPaint.measureText(evaluationTime);
canvas.drawText(evaluationTime,radus - textLen3 / 2,radus/2+beta_hight*3+rt2.height()+rt1.height()+rt3.height(),pgPaint);
方法
/** * 获取当前时间 * * @return */
public String getCurrentTime()
{
@SuppressLint("SimpleDateFormat")
SimpleDateFormat format = new SimpleDateFormat("yyyy:MM:dd");
return format.format(new Date());
}
//数字动画
public void startAnim()
{
ValueAnimator mAngleAnim = ValueAnimator.ofFloat(progress, mTotalAngle);
mAngleAnim.setInterpolator(new AccelerateDecelerateInterpolator());
mAngleAnim.setDuration(5000);
mAngleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
progress = (float) valueAnimator.getAnimatedValue();
postInvalidate();
}
});
mAngleAnim.start();
ValueAnimator mNumAnim = ValueAnimator.ofInt(mMinNum, mMaxNum);
mNumAnim.setDuration(5000);
mNumAnim.setInterpolator(new LinearInterpolator());
mNumAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
mMinNum = (int) valueAnimator.getAnimatedValue();
postInvalidate();
}
});
mNumAnim.start();
}
//设置信用等级350~950之间
public void setSesameValues(int values)
{
if (values <= 350)
{
mMaxNum = values;
mTotalAngle = 0f;
sesameLevel = "信用较差";
evaluationTime = "评估时间:" + getCurrentTime();
} else if (values <= 550)
{
mMaxNum = values;
mTotalAngle = (values - 350) * 80 / 400f + 2;
sesameLevel = "信用较差";
evaluationTime = "评估时间:" + getCurrentTime();
} else if (values <= 700)
{
mMaxNum = values;
if (values > 550 && values <= 600)
{
sesameLevel = "信用中等";
} else if (values > 600 && values <= 650)
{
sesameLevel = "信用良好";
} else
{
sesameLevel = "信用优秀";
}
mTotalAngle = (values - 550) * 120 / 150f + 43;
evaluationTime = "评估时间:" + getCurrentTime();
} else if (values <= 950)
{
mMaxNum = values;
mTotalAngle = (values - 700) * 40 / 250f + 170;
sesameLevel = "信用极好";
evaluationTime = "评估时间:" + getCurrentTime();
} else
{
mTotalAngle = 240f;
}
startAnim();
}
在Activity初始化并调用
mv= (MyView) findViewById(R.id.mv);
mv.setSesameValues(657);
效果
private Paint mBitmapPaint;//小圆点画笔
private float[] cir_location;//小圆点的实际位置
mBitmapPaint = new Paint();
mBitmapPaint.setStyle(Paint.Style.FILL);
mBitmapPaint.setColor(Color.WHITE);
mBitmapPaint.setAntiAlias(true);
cir_location = new float[2];
//绘制外环进度
canvas.drawArc(rf,-195,progress,false,wwPaint);//总360
//绘制外环小圆点
Path path = new Path();
path.addArc(rf, -195, progress);
PathMeasure pathMeasure = new PathMeasure(path, false);
pathMeasure.getPosTan(pathMeasure.getLength() * 1, cir_location, null);
mBitmapPaint.setColor(Color.WHITE);
canvas.drawCircle(cir_location[0], cir_location[1], 8, mBitmapPaint);
canvas.drawCircle(cir_location[0], cir_location[1], 8, mBitmapPaint);