先看一下腾讯管家的测速控件

其中可以看出来测速控件分为两个作用一个是测量延时,一个是测网速
所以可以将控件分为两部分,然后用一个ViewGroup将两个View装载在一起。
好了,分析的话就说这么多,下面开始看第一部分测量网络延时的源码
`
public class DelayMeterView extends View {
Paint dottedPoint;//最外层画笔
float time;//动画时间
float dottedRadius;//外围圆的半径
public float getTime() {
return time;
}
public void setDottedRadius(float dottedRadius) {
this.dottedRadius = dottedRadius;
}
public void setTime(float time) {
this.time = time;
invalidate();
}
ObjectAnimator objectAnimator;//动画
public DelayMeterView(Context context) {
this(context, null);
}
public DelayMeterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DelayMeterView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
dottedPoint = new Paint(Paint.ANTI_ALIAS_FLAG);
objectAnimator = ObjectAnimator.ofFloat(this, "time", 0, 60);
objectAnimator.setDuration(1000 * 5);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("onDraw", "onDraw333");
canvas.translate(getWidth() / 2, getHeight() / 2);
canvasDotted(canvas);
}
public void canvasDotted(Canvas canvas) {
PathEffect pathEffect = new DashPathEffect(new float[]{10, 5}, 10);//画虚线
dottedPoint.setPathEffect(pathEffect);
dottedPoint.setColor(Color.parseColor("#C4E7D5"));
dottedPoint.setStyle(Paint.Style.STROKE);
dottedPoint.setStrokeWidth(10);
RectF rectF = new RectF(-dottedRadius, -dottedRadius, dottedRadius, dottedRadius);
canvas.drawArc(rectF, 135, 270 * (time / 60), false, dottedPoint);
}
public void setAnimaStart() {
Log.e("", "");
objectAnimator.start();
}
public void stopAniam() {
objectAnimator.end();
}
}
`
这段代码就不用解释了 就是画一个最外围的圆环 其中canvasDotted方法需要看一下
下面是第二部分测量网速的view
`
public class SpeedMeterView extends View {
Paint unitPaint;//单位的画笔
Paint pointerPaint;//指针画笔
Paint textPaint;//实际网速的画笔
String textUnit = "KB/s";
int value = 0;//默认网速
Rect textRect = new Rect();
float preAngle = 0;//前一个指针偏转的角度
float nextAngle = 0;//前一个指针偏转的角度
float smallRadius = 120; //小圆半径
ObjectAnimator objectAnimator;
float time;
float angle = 0;//偏转角度
public float getTime() {
return time;
}
public void setTime(float time) {
this.time = time;
angle = preAngle + (nextAngle - preAngle) * time / 100;
invalidate();
}
public int getValue() {
return value;
}
public void setValue(int value) {
if (!objectAnimator.isRunning()) {
this.value = value;
setAngle();
objectAnimator.start();
}
}
/**
* 计算偏转角度 角度按照50 45 40 35 30 25 20 分配
*/
public void setAngle() {
if (value < 64) {
nextAngle = value * 50 / 64;
} else if (value < 128) {
nextAngle = 50 + (value - 64) * 45 / 64;
} else if (value < 256) {
nextAngle = 50 + 45 + (value - 128) * 40 / 128;
} else if (value < 512) {
nextAngle = 50 + 45 + 40 + (value - 256) * 35 / 256;
} else if (value < 1024) {
nextAngle = 50 + 45 + 40 + 35 + (value - 512) * 30 / 512;
} else if (value < 5120) {
nextAngle = 50 + 45 + 40 + 35 + 30 + value * 25 / 4096;
} else {
nextAngle = 50 + 45 + 40 + 35 + 30 + 25 + value * 20 / 4096;
}
}
public SpeedMeterView(Context context) {
this(context, null);
}
public SpeedMeterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SpeedMeterView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pointerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
unitPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pointerPaint.setStrokeWidth(6);
objectAnimator = ObjectAnimator.ofFloat(this, "time", 0, 100);
objectAnimator.setDuration(300);
objectAnimator.setInterpolator(new LinearInterpolator());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("onDraw", "onDraw222");
canvas.translate(getWidth() / 2, getHeight() / 2);
canvasNum(canvas);
canvasUnit(canvas);
canvasPointer(canvas);
}
/**
* 绘制网速数字
*
* @param canvas
*/
public void canvasNum(Canvas canvas) {
textPaint.setColor(Color.parseColor("#000000"));
textPaint.setFakeBoldText(true);
String num = value + "";
textPaint.setTextSize(50);
textPaint.getTextBounds(num, 0, num.length(), textRect);
canvas.drawText(num, -textRect.width() / 2, textRect.height() / 2, textPaint);
}
/**
* 绘制单位
*
* @param canvas
*/
public void canvasUnit(Canvas canvas) {
unitPaint.setColor(Color.parseColor("#8f8f8f"));
Rect rect = new Rect();
unitPaint.setTextSize(26);
unitPaint.getTextBounds(textUnit, 0, textUnit.length(), rect);
canvas.drawText(textUnit, -rect.width() / 2, rect.height() / 2 + textRect.height() / 2 + 20, unitPaint);
}
/**
* 绘制指针
*
* @param canvas
*/
public void canvasPointer(Canvas canvas) {
float startX = (float) (smallRadius * Math.cos((135 + angle) * Math.PI / 180));
float startY = (float) (smallRadius * Math.sin((135 + angle) * Math.PI / 180));
float startX1 = (float) (220 * Math.cos((135 + angle) * Math.PI / 180));
float startY1 = (float) (220 * Math.sin((135 + angle) * Math.PI / 180));
Shader shader1 = new LinearGradient(startX, startY, startX1, startY1, Color.parseColor("#eee9eb"),
Color.parseColor("#D69087"), Shader.TileMode.CLAMP);
pointerPaint.setShader(shader1);
pointerPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(startX, startY, startX1, startY1, pointerPaint);
}
`
这段代码画的东西有很多 不过都有注释 耐心看一下 应该能看懂
最后就是用ViewGroup组装两个view 效果图
git地址:https://github.com/flyMountain/TianTianQuan