一个三环评分控件
效果:
代码:
<declare-styleable name="ScoreCircleView">
<attr name="sbackWidth" format="dimension" /> <!--背景圆环宽度-->
<attr name="sprogWidth" format="dimension" /> <!--进度圆环宽度-->
<attr name="sbackColor" format="color" /> <!--背景圆环颜色-->
<attr name="sprogTextColor" format="color" />
<attr name="sprogTextSize" format="dimension" />
<attr name="sprogStartColor" format="color" /> <!--进度圆环开始颜色-->
<attr name="sprogFirstColor" format="color" /> <!--进度圆环结束颜色-->
<attr name="sprogOneColor" format="color" /> <!--进度圆环结束颜色-->
<attr name="sprogTwoColor" format="color" /> <!--进度圆环结束颜色-->
<attr name="sprogThreeColor" format="color" /> <!--进度圆环结束颜色-->
<attr name="sprogress" format="integer" /> <!--圆环进度-->
</declare-styleable>
public class ScoreCircleView extends View {
private Paint mBackPaint, mProgPaint,mTextPaint; // 绘制画笔
private RectF mRectF; // 绘制区域
private int[] mColorArray; // 圆环渐变色
public float mTextWidth;
public float mTextHeight;
public int POneColor;
public int PTwoColor;
public int PThreeColor;
public ScoreCircleView(Context context) {
this(context, null);
}
public ScoreCircleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ScoreCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@SuppressLint("Recycle")
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScoreCircleView);
POneColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogOneColor, Color.BLUE);
PTwoColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogTwoColor, Color.BLUE);
PThreeColor=typedArray.getColor(R.styleable.ScoreCircleView_sprogThreeColor, Color.BLUE);
// 初始化背景圆环画笔
mBackPaint = new Paint();
mBackPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充
mBackPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆角
mBackPaint.setAntiAlias(true); // 设置抗锯齿
mBackPaint.setDither(true); // 设置抖动
mBackPaint.setStrokeWidth(typedArray.getDimension(R.styleable.ScoreCircleView_sbackWidth, 5));
mBackPaint.setColor(typedArray.getColor(R.styleable.ScoreCircleView_sbackColor, Color.LTGRAY));
// 初始化进度圆环画笔
mProgPaint = new Paint();
mProgPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充
mProgPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆角
mProgPaint.setAntiAlias(true); // 设置抗锯齿
mProgPaint.setDither(true); // 设置抖动
mProgPaint.setStrokeWidth(typedArray.getDimension(R.styleable.ScoreCircleView_sprogWidth, 10));
//初始化文本
mTextPaint=new Paint();
mTextPaint.setTextAlign(Paint.Align.RIGHT);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setAntiAlias(true); // 设置抗锯齿
mTextPaint.setDither(true); // 设置抖动
mTextPaint.setTextSize(typedArray.getDimension(R.styleable.ScoreCircleView_sprogTextSize,16));
mTextPaint.setColor(typedArray.getColor(R.styleable.ScoreCircleView_sprogTextColor, Color.BLACK));
// 初始化进度圆环渐变色
int startColor = typedArray.getColor(R.styleable.ScoreCircleView_sprogStartColor, -1);
int firstColor = typedArray.getColor(R.styleable.ScoreCircleView_sprogFirstColor, -1);
if (startColor != -1 && firstColor != -1) mColorArray = new int[]{startColor, firstColor};
else mColorArray = null;
typedArray.recycle();
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int viewWide = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int viewHigh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
int mRectLength = (int) ((viewWide > viewHigh ? viewHigh : viewWide) - (mBackPaint.getStrokeWidth() > mProgPaint.getStrokeWidth() ? mBackPaint.getStrokeWidth() : mProgPaint.getStrokeWidth()));
int mRectL = getPaddingLeft() + (viewWide - mRectLength) / 2;
int mRectT = getPaddingTop() + (viewHigh - mRectLength) / 2;
mRectF = new RectF(mRectL, mRectT, mRectL + mRectLength, mRectT + mRectLength);
// // 设置进度圆环渐变色
// if (mColorArray != null && mColorArray.length > 1)
// mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
//
}
int mStrokWidth=dp2px(30);
int mTextMargin=dp2px(18);
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mRectF, 270,270 , false, mBackPaint);
canvas.drawArc(mRectF.left+mStrokWidth,mRectF.top+mStrokWidth,mRectF.right-mStrokWidth,mRectF.bottom-mStrokWidth,270,270,false,mBackPaint);
canvas.drawArc(mRectF.left+mStrokWidth*2,mRectF.top+mStrokWidth*2,mRectF.right-mStrokWidth*2,mRectF.bottom-mStrokWidth*2,270,270,false,mBackPaint);
for (int i = 0; i < list.size(); i++) {
if (i==0){
mProgPaint.setColor(getProgressColor(i));
canvas.drawArc(mRectF, 270, 270 *presont*list.get(i).getValues() / 100, false, mProgPaint);
}else
{
mProgPaint.setColor(getProgressColor(i));
canvas.drawArc(mRectF.left+mStrokWidth*i,mRectF.top+mStrokWidth*i,mRectF.right-mStrokWidth*i,mRectF.bottom-mStrokWidth*i,270,270 *presont*list.get(i).getValues() / 100,false,mProgPaint);
}
}
for (int i = 0; i < list.size(); i++) {
Rect rect = new Rect();
mTextPaint.getTextBounds(list.get(i).getName(),0,list.get(i).getName().length(),rect);
int textHeight = rect.height()/4;
canvas.drawText(list.get(i).getName(),getMeasuredWidth()/2-mTextMargin,mRectF.top+mStrokWidth*i+textHeight,mTextPaint);
}
}
/**
* 初始化界面
*/
public void init() {
ValueItem item1=new ValueItem("力度",00);
ValueItem item2=new ValueItem("时长",00);
ValueItem item3=new ValueItem("区域",00);
ArrayList<ValueItem> objects = new ArrayList<>();
objects.add(item1);
objects.add(item2);
objects.add(item3);
setValues(objects,3000);
}
/**
* 返回对应的样色
* @param i
* @return
*/
public int getProgressColor(int i){
switch (i){
case 0:
return POneColor;
case 1:
return PTwoColor;
case 2:
return PThreeColor;
}
return POneColor;
}
/**
* dp转px
*/
private int dp2px(float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, getContext().getResources().getDisplayMetrics());
}
/**
* 设置背景圆环颜色
*
* @param color 背景圆环颜色
*/
public void setBackColor(@ColorRes int color) {
mBackPaint.setColor(ContextCompat.getColor(getContext(), color));
invalidate();
}
/**
* 设置进度圆环宽度
*
* @param width 进度圆环宽度
*/
public void setProgWidth(int width) {
mProgPaint.setStrokeWidth(width);
invalidate();
}
float presont=0;
List<ValueItem> list=new ArrayList<>();
public void setValues(List<ValueItem> list,long animTime){
this.list=list;
if (animTime <= 0) {
}
else {
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
presont = (float) animation.getAnimatedValue();
invalidate();
}
});
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(animTime);
animator.start();
}
}
/**
* 设置进度圆环颜色(支持渐变色)
*
* @param startColor 进度圆环开始颜色
* @param firstColor 进度圆环结束颜色
*/
public void setProgColor(@ColorRes int startColor, @ColorRes int firstColor) {
mColorArray = new int[]{ContextCompat.getColor(getContext(), startColor), ContextCompat.getColor(getContext(), firstColor)};
mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
invalidate();
}
/**
* 设置进度圆环颜色(支持渐变色)
*
* @param colorArray 渐变色集合
*/
public void setProgColor(@ColorRes int[] colorArray) {
if (colorArray == null || colorArray.length < 2) return;
mColorArray = new int[colorArray.length];
for (int index = 0; index < colorArray.length; index++)
mColorArray[index] = ContextCompat.getColor(getContext(), colorArray[index]);
mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));
invalidate();
}
public class ValueItem{
String name;
float values;
public ValueItem(String name, float values) {
this.name = name;
this.values = values;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getValues() {
return values;
}
public void setValues(float values) {
this.values = values;
}
}
一个中心扩散雷达 控件
效果
代码
public class WaterWave extends View {
private float mInitialRadius; // 初始波纹半径
private float mMaxRadiusRate = 0.95f; // 如果没有设置mMaxRadius,可mMaxRadius = 最小长度 * mMaxRadiusRate;
private float mMaxRadius; // 最大波纹半径
private long mDuration = 3000; // 一个波纹从创建到消失的持续时间
private int mSpeed = 800; // 波纹的创建速度,每500ms创建一个
private Interpolator mInterpolator = new LinearInterpolator();
private List<Circle> mCircleList = new ArrayList<Circle>();
private boolean mIsRunning;
private boolean mMaxRadiusSet;
private Paint mPaint;
private long mLastCreateTime;
private Runnable mCreateCircle = new Runnable() {
@Override
public void run() {
if (mIsRunning) {
newCircle();
postDelayed(mCreateCircle, mSpeed);
}
}
};
public WaterWave(Context context) {
this(context, null);
}
public WaterWave(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
setStyle(Paint.Style.FILL);
// mPaint.setStrokeWidth(4);
mPaint.setColor(Color.parseColor("#3F3F51"));
}
public void setStyle(Paint.Style style) {
mPaint.setStyle(style);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (!mMaxRadiusSet) {
mMaxRadius = Math.min(w, h) * mMaxRadiusRate / 2.0f;
}
start();
}
public void setMaxRadiusRate(float maxRadiusRate) {
this.mMaxRadiusRate = maxRadiusRate;
}
public void setColor(int color) {
mPaint.setColor(color);
}
/**
* 开始
*/
public void start() {
if (!mIsRunning) {
mIsRunning = true;
mCreateCircle.run();
}
}
/**
* 停止
*/
public void stop() {
mIsRunning = false;
}
protected void onDraw(Canvas canvas) {
Iterator<Circle> iterator = mCircleList.iterator();
while (iterator.hasNext()) {
Circle circle = iterator.next();
if (System.currentTimeMillis() - circle.mCreateTime < mDuration) {
mPaint.setAlpha(circle.getAlpha());
mPaint.setShader(new RadialGradient(getWidth() / 2,getHeight() / 2,circle.getCurrentRadius(),new int[]{0xFFBC60C4,0xFF5C63FA},new float[]{0.3f,0.8f}, Shader.TileMode.CLAMP));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, circle.getCurrentRadius(), mPaint);
} else {
iterator.remove();
}
}
if (mCircleList.size() > 0) {
postInvalidateDelayed(10);
}
}
public void setInitialRadius(float radius) {
mInitialRadius = radius;
}
public void setDuration(long duration) {
this.mDuration = duration;
}
public void setMaxRadius(float maxRadius) {
this.mMaxRadius = maxRadius;
mMaxRadiusSet = true;
}
public void setSpeed(int speed) {
mSpeed = speed;
}
private void newCircle() {
long currentTime = System.currentTimeMillis();
if (currentTime - mLastCreateTime < mSpeed) {
return;
}
Circle circle = new Circle();
mCircleList.add(circle);
invalidate();
mLastCreateTime = currentTime;
}
private class Circle {
private long mCreateTime;
public Circle() {
this.mCreateTime = System.currentTimeMillis();
}
public int getAlpha() {
float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
return (int) ((1.0f - mInterpolator.getInterpolation(percent)) * 255);
}
public float getCurrentRadius() {
float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius);
}
}
public void setInterpolator(Interpolator interpolator) {
mInterpolator = interpolator;
if (mInterpolator == null) {
mInterpolator = new LinearInterpolator();
}
}
}
一个 带分数的进度条 自定义控件
效果:
代码:
public class ProgressBar extends View implements View.OnClickListener {
private String TAG = this.getClass().getName();
public UsmileProgressBar(Context context) {
this(context, null);
}
public ProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
Paint mBarPaint;
Paint mBarBgPaint;
Paint mRriangPaint;//三角形
Paint mTextPaint;//文字
Path mRriangPath;
int BasePadding = dipToPx(getContext(), 10);
private void init() {
mBarBgPaint = new Paint();
mBarBgPaint.setStyle(Paint.Style.FILL);
mBarBgPaint.setColor(Color.parseColor("#222329"));
mBarPaint = new Paint();
mBarPaint.setStyle(Paint.Style.FILL);
mRriangPaint = new Paint();
mRriangPaint.setStyle(Paint.Style.FILL);
mRriangPaint.setColor(Color.BLUE);
mTextPaint = new Paint();
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
mRriangPath = new Path();
setOnClickListener(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setValues(100, true);
}
int DefWidth = dipToPx(getContext(), 240);
int DefHeight = dipToPx(getContext(), 50);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeWith = MeasureSpec.getSize(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//根据模式来 决定宽度
switch (modeWidth) {
case MeasureSpec.EXACTLY://match_parent 精确的度数
DefWidth = sizeWith;
break;
case MeasureSpec.AT_MOST://wrap_content 适配的度数
break;
}
//根据模式来 决定宽度
switch (modeHeight) {
case MeasureSpec.EXACTLY://match_parent 精确的度数
DefHeight = sizeHeight;
break;
case MeasureSpec.AT_MOST://wrap_content 适配的度数
break;
}
setMeasuredDimension(DefWidth, DefHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawLable(canvas);
drawSorce(canvas);
drawRriang(canvas);
drawProgress(canvas);
}
String LableSorce = "80分";
private void drawSorce(Canvas canvas) {
float mtextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(24f);
mTextPaint.setColor(Color.WHITE);
canvas.drawText(LableSorce, BarLenght - BasePadding, getHeight() / 2 - BarHeigth / 2 - mtextHeight, mTextPaint);
}
String LableStart = "0分";
String LableEnd = "100分";
int textHeight = 24;
private void drawLable(Canvas canvas) {
mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setTextSize(24f);
mTextPaint.setColor(Color.parseColor("#83838C"));
canvas.drawText(LableStart, 0 + BasePadding, getHeight() / 2 + BarHeigth / 2 + textHeight, mTextPaint);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(LableEnd, getWidth() - BasePadding, getHeight() / 2 + BarHeigth / 2 + textHeight, mTextPaint);
}
// 三角形
int mRriangHeight = dipToPx(getContext(), 10);
int mRriangWidth = dipToPx(getContext(), 14);
//绘制三角形
private void drawRriang(Canvas canvas) {
mRriangPath.reset();
mRriangPath.moveTo(BarLenght + BasePadding, getHeight() / 2 + BarHeigth / 2);
mRriangPath.lineTo(BarLenght + mRriangWidth / 2 + BasePadding, getHeight() / 2 + BarHeigth / 2 + mRriangHeight);
mRriangPath.lineTo(BarLenght - mRriangWidth / 2 + BasePadding, getHeight() / 2 + BarHeigth / 2 + mRriangHeight);
mRriangPath.close();
canvas.drawPath(mRriangPath, mRriangPaint);
}
int BarHeigth = dipToPx(getContext(), 10);
//进度长度
float BarLenght = 180;
private void drawProgress(Canvas canvas) {
RectF rectFBg = new RectF(0 + BasePadding, (getHeight() - BarHeigth) / 2, getWidth() - BasePadding, (getHeight() - BarHeigth) / 2 + BarHeigth);
canvas.drawRoundRect(rectFBg, 20, 20, mBarBgPaint);
mBarPaint.setShader(new LinearGradient(0f, 0f, getWidth(), 0f, new int[]{0xFF4E90FC, 0xFF2C7BFB, 0xFF3984FD}, new float[]{0f, 0.5f, 0.9f}, CLAMP));
RectF rectF = new RectF(0 + BasePadding, (getHeight() - BarHeigth) / 2, BarLenght + BasePadding, (getHeight() - BarHeigth) / 2 + BarHeigth);
canvas.drawRoundRect(rectF, 20, 20, mBarPaint);
}
/**
* dip 转换成px
*
* @param dip
* @return
*/
public static int dipToPx(Context context, float dip) {
float density = context.getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}
ValueAnimator animator;
public void setValues(float values, boolean isAnimation) {
Log.i(TAG, "setValues: width:" + getWidth());
if (isAnimation) {
if (animator != null) {
animator.cancel();
animator.setFloatValues(0, values);
animator.start();
} else {
animator = ValueAnimator.ofFloat(0f, values);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float animatedValue = (float) valueAnimator.getAnimatedValue();
BarLenght = (float) (animatedValue * (getWidth() - BasePadding * 2) / 100);
Log.i(TAG, "setValues: valueAnimator:" + animatedValue);
Log.i(TAG, "setValues: BarLenght:" + BarLenght);
LableSorce = (int) animatedValue + "分";
postInvalidate();
}
});
animator.setDuration(3000);
}
animator.start();
} else {
BarLenght = (float) (values * (getWidth() - BasePadding * 2) / 100);
LableSorce = (int) values + "分";
postInvalidate();
}
}
@Override
public void onClick(View view) {
setValues(100, true);
}
}
一个类似支付宝 分数自定义控件
效果
代码
public class CirlcleBar extends View implements View.OnClickListener {
Paint mRadarPaint;
// 弧度的宽度
int mBarWidth = 20;
float TextHeight = 0;
int BarBgColor = Color.WHITE;
String sorce = "";
String sorceLabel = "分";
String defaultLabel = "上次刷牙得分";
Paint mTextPaint;
float currentDegress ;//当前角度
float currentSorce ;//当前分数
float maxDegress = 220f;
int mRadius = 0;
int DefaultDegress = 160;
int mRadarMargin = dipToPx(getContext(), 3);
int DefWidth = dipToPx(getContext(), 240);
int DefHeight = dipToPx(getContext(), 120);
Paint mBarBgPaint;
Paint mBarPaint;
private String TAG = getClass().getName();
public UsmileCirlcleBar(Context context) {
this(context, null);
}
public CirlcleBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CirlcleBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mAttr(context, attrs, defStyleAttr);
}
float SorceSize;
float SorceLableSize;
float DefaultLableSize;
String DefaultLable = "上次刷牙得分";
Paint mLittleCirlcePaint;
int mLittleRadius;
//获取属性
private void mAttr(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UsmileCircleBar, defStyleAttr, 0);
SorceSize = typedArray.getDimension(R.styleable.UsmileCircleBar_mSorceSize, 72);
SorceLableSize = typedArray.getDimension(R.styleable.UsmileCircleBar_mSorceLableSize, 42);
DefaultLableSize = typedArray.getDimension(R.styleable.UsmileCircleBar_DefaultLableSize, 42);
DefaultLable = typedArray.getString(R.styleable.UsmileCircleBar_DefaultLabe);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
init();
}
private void init() {
mRadarPaint = new Paint();
mRadarPaint.setStyle(Paint.Style.FILL);
mRadarPaint.setStrokeWidth(20);
mRadarPaint.setAntiAlias(true);
mBarBgPaint = new Paint();
mBarBgPaint.setStyle(Paint.Style.STROKE);
mBarBgPaint.setStrokeWidth(mBarWidth);
mBarBgPaint.setStrokeCap(Paint.Cap.ROUND);
mBarBgPaint.setColor(BarBgColor);
mBarBgPaint.setAntiAlias(true);
mBarBgPaint.setAlpha(50);
mBarPaint = new Paint();
mBarPaint.setColor(Color.BLUE);
mBarPaint.setStyle(Paint.Style.STROKE);
mBarPaint.setStrokeWidth(mBarWidth);
mBarPaint.setAntiAlias(true);
mBarPaint.setStrokeCap(Paint.Cap.ROUND);
mTextPaint = new Paint();
mLittleCirlcePaint=new Paint();
mLittleCirlcePaint.setStyle(Paint.Style.FILL);
setLayerType(View.LAYER_TYPE_SOFTWARE,mLittleCirlcePaint);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setAntiAlias(true);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
TextHeight = (fontMetrics.bottom - fontMetrics.top) / 2;
try {
/* Uri uri=Uri.parse("android:resource://"+getContext().getPackageName()+"/"+R.font.alibaba_puhuiti_medium);
mTextPaint.setTypeface(Typeface.createFromFile(uri.getPath()));*/
mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/alibaba_puhuiti_medium.otf"));
} catch (Exception e) {
e.printStackTrace();
}
//宽高 最短 的作为 直径
mRadius = Math.min(getWidth() / 2, getHeight()/2);
mLittleRadius= (int) (mRadius*0.5);
setOnClickListener(this);
//测试
setValues(80, true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeWith = MeasureSpec.getSize(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//根据模式来 决定宽度
switch (modeWidth) {
case MeasureSpec.EXACTLY://match_parent 精确的度数
DefWidth = sizeWith;
break;
case MeasureSpec.AT_MOST://wrap_content 适配的度数
break;
}
//根据模式来 决定宽度
switch (modeHeight) {
case MeasureSpec.EXACTLY://match_parent 精确的度数
DefHeight = sizeHeight;
break;
case MeasureSpec.AT_MOST://wrap_content 适配的度数
break;
}
setMeasuredDimension(DefWidth, DefHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBarBg(canvas);
drawBar(canvas);
drawRadar(canvas);
drawLittelCirle(canvas);
drawText(canvas);
}
private void drawLittelCirle(Canvas canvas) {
canvas.save();
canvas.translate(getWidth() / 2, getHeight()/2);
mLittleCirlcePaint.setColor(Color.parseColor("#393948"));
mLittleCirlcePaint.setMaskFilter(new BlurMaskFilter(mLittleRadius*0.1f, BlurMaskFilter.Blur.SOLID));
canvas.drawCircle(0,0,mLittleRadius,mLittleCirlcePaint);
mLittleCirlcePaint.setColor(Color.parseColor("#2F2F3A"));
mLittleCirlcePaint.setMaskFilter(new BlurMaskFilter(mLittleRadius*0.1f, BlurMaskFilter.Blur.OUTER));
canvas.drawCircle(0,0,mLittleRadius,mLittleCirlcePaint);
canvas.restore();
}
//字体
private void drawText(Canvas canvas) {
canvas.save();
canvas.translate(getWidth() / 2, getHeight()/2);
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(SorceSize);
TextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;
sorce= ((int) currentSorce)+"";
//分数
mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_medium.otf"));
mTextPaint.setAlpha(255);
canvas.drawText(sorce, 0, 0, mTextPaint);
//分标签
float soreceStrWidth = mTextPaint.measureText(sorce);
mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setAlpha(201);
mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_regular.otf"));
mTextPaint.setTextSize(SorceLableSize);
canvas.drawText(sorceLabel, soreceStrWidth / 2, 0, mTextPaint);
//上次刷牙得分
TextHeight = (mTextPaint.getFontMetrics().bottom - mTextPaint.getFontMetrics().top) / 2;
mTextPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"font/alibaba_puhuiti_regular.otf"));
mTextPaint.setAlpha(153);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(DefaultLableSize);
canvas.drawText(defaultLabel, 0, TextHeight*2, mTextPaint);
canvas.restore();
}
//当前进度
private void drawBar(Canvas canvas) {
canvas.save();
canvas.translate(getWidth() / 2, getHeight()/2);
RectF mRectf = new RectF(-mRadius + mBarWidth / 2, -mRadius + mBarWidth / 2, mRadius - mBarWidth / 2, mRadius - mBarWidth / 2);
mBarPaint.setShader(new LinearGradient(-mRadius+mBarWidth/2,0,mRadius-mBarWidth/2,0,new int[]{0xFFBC60C4,0xFF5C63FA},new float[]{0.3f,0.8f}, Shader.TileMode.CLAMP));
canvas.drawArc(mRectf, DefaultDegress, currentDegress, false, mBarPaint);
canvas.restore();
}
int BasePadding=dipToPx(getContext(),8);
//弧度的背景色
private void drawBarBg(Canvas canvas) {
canvas.save();
canvas.translate(getWidth() / 2, getHeight()/2);
/*去掉进度条宽度*/
RectF mRectf = new RectF(-mRadius + mBarWidth / 2, -mRadius + mBarWidth / 2, mRadius - mBarWidth / 2, mRadius - mBarWidth / 2);
canvas.drawArc(mRectf, DefaultDegress, maxDegress, false, mBarBgPaint);
canvas.restore();
}
/*雷达弧*/
public void drawRadar(Canvas canvas) {
canvas.save();
canvas.translate(getWidth() / 2, getHeight()/2);
//画扫描
mRadarPaint.setShader(new SweepGradient(0, 0, new int[]{Color.TRANSPARENT, 0x555C63FA}, new float[]{0.95F, 0.99F}));
canvas.rotate(DefaultDegress + currentDegress);
RectF mRect = new RectF(-mRadius + mBarWidth + mRadarMargin, -mRadius + mBarWidth + mRadarMargin, mRadius - mBarWidth - mRadarMargin, mRadius - mBarWidth - mRadarMargin);
canvas.drawArc(mRect, 0, 360, true, mRadarPaint);
canvas.restore();
}
ValueAnimator mValueAnimator;
int mValues=0;
public void setValues(final int values, boolean isAnm) {
mValues=values;
if (isAnm) {
if (mValueAnimator != null) {
mValueAnimator.cancel();
mValueAnimator.setIntValues(0, values);
mValueAnimator.start();
} else {
mValueAnimator = ValueAnimator.ofInt(0, values);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
currentDegress = (maxDegress-DefaultDegress)*animatedValue/100;
currentSorce=animatedValue;
postInvalidate();
}
});
mValueAnimator.setDuration(3000);
mValueAnimator.start();
}
} else {
currentDegress = values;
postInvalidate();
}
}
@Override
public void onClick(View v) {
if (mValueAnimator.isRunning()) {
return;
} else {
mValueAnimator.start();
}
}
/**
* dip 转换成px
*
* @param dip
* @return
*/
public static int dipToPx(Context context, float dip) {
float density = context.getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}
}