最近项目需要,要求画一个体重秤,最为外界体重秤不能使用时的备用,让用户手动选择一个体重值。这里就是纯粹为了将自己实现的经过记录下,方便以后自己整理回顾,仅作为记录用。
开始的时候,是想通过画圆扇形canvas.drawArc(new RectF(left,top,right,bottom), startAngle, sweepAngle, useCenter, paint)来实现,这里着重了解了下第四个参数useCenter(:If true, include the center of the oval in the arc, and close it if it is being stroked. This will draw a wedge.)如果true则包含扇形的整个区域,如果false则只画弧线。
用canvas.drawArc循环360度,画扇形,这样可以画出一条条连接到圆心的实现,在通过画一个白色的扇形来遮掩多余的到圆形的实线,这样就可以画出360个短刻度;同理将长刻度画出来。但是问题是,整个屏幕有张背景图,用白色去画圆遮盖的那部分就是一个大白圆,尝试用canvas.clipPath想去抠掉那部分,抠来抠去也没抠掉,没办法,看来只能换思路。
既然画扇形不行,那我就画弧线,画上下两条弧线作为体重秤的外延,再在里面划上刻度,应该就不存在与背景图片不搭的尴尬了。
想到就做,先画两条弧线:
canvas.drawArc(new RectF(-MARGIN_TOP_OF_ARC-r/2, MARGIN_TOP-MARGIN_TOP_OF_ARC, r+MARGIN_TOP_OF_ARC+r/2, r+MARGIN_TOP+MARGIN_TOP_OF_ARC+r), 245, 50, false, sectorPaint);
canvas.drawArc(new RectF(MARGIN_TOP_OF_SMALL_ARC-r/2, MARGIN_TOP+MARGIN_TOP_OF_SMALL_ARC, -MARGIN_TOP_OF_SMALL_ARC+r+r/2, -MARGIN_TOP_OF_SMALL_ARC+r+MARGIN_TOP+r),245 , 50, false, sectorPaint);
然后再画两条实线来连接这两条弧线的顶点:
float startX,startX1=0,startY,startY1=0,stopX,stopX1=0,stopY,stopY1=0;
startX = (float) (r/2 - (r+MARGIN_TOP_OF_ARC)*Math.cos(65*Math.PI/180));
startY = (float) (r+MARGIN_TOP - (r+MARGIN_TOP_OF_ARC)*Math.sin(65*Math.PI/180));
stopX = (float) (r/2 - (r-MARGIN_TOP_OF_SMALL_ARC)*Math.cos(65*Math.PI/180));
stopY = (float) (r+MARGIN_TOP - ((r-MARGIN_TOP_OF_SMALL_ARC)*Math.sin(65*Math.PI/180)));
canvas.drawLine(startX, startY, stopX, stopY, sectorPaint);
startX1 = (float) (r/2+(r+MARGIN_TOP_OF_ARC)*Math.cos(65*Math.PI/180));
startY1 = startY;
stopX1 = (float) (r/2+(r-MARGIN_TOP_OF_SMALL_ARC)*Math.cos(65*Math.PI/180));
stopY1 = stopY;
canvas.drawLine(startX1, startY1, stopX1, stopY1, sectorPaint);
再画出刻度:
FontMetrics fm = anglePaint.getFontMetrics();
linePaint.setColor(Color.BLACK);
linePaint.setStyle(Style.FILL);
float currentRadian = 0;
for(float i=0;i<=360;i++){
currentRadian = touch_offset + i + offest;
if(currentRadian + 2 >= 270 && currentRadian + 2 <=272){
//计算当前所指刻度
int f = (int)((270 - currentRadian)/2*10);
if(i+((float)f)/10 < 0){
weight = 0;
}else if(i+((float)f)/10 > 360){
weight = 360;
}else
weight = i+((float)f)/10;
}
float startX=0,startY=0,stopX=0,stopY=0;
float textOffestY = 20;
// float textW = anglePaint.measureText((int)i+"");
float textH = (float)(Math.ceil(fm.descent - fm.ascent) + 2);
anglePaint.setTextAlign(Align.CENTER);
textOffestY = 0 + textH;
textOffestY+=10;
if(currentRadian >= 250 && currentRadian<=270){
currentRadian = currentRadian - 180;
if(i%5 != 0){
startX = (float) (r/2 - r*Math.cos(currentRadian*Math.PI/180));
startY = (float) (r+MARGIN_TOP - r*Math.sin(currentRadian*Math.PI/180));
stopX = (float) (r/2 - (r-GRADUATION_SHORT)*Math.cos(currentRadian*Math.PI/180));
stopY = (float) (r+MARGIN_TOP - ((r-GRADUATION_SHORT)*Math.sin(currentRadian*Math.PI/180)));
canvas.drawLine(startX, startY, stopX, stopY, linePaint);
}else{
startX = (float) (r/2 - r*Math.cos(currentRadian*Math.PI/180));
startY = (float) (r+MARGIN_TOP - r*Math.sin(currentRadian*Math.PI/180));
stopX = (float) (r/2 - (r-GRADUATION_LONG)*Math.cos(currentRadian*Math.PI/180));
stopY = (float) (r+MARGIN_TOP - ((r-GRADUATION_LONG)*Math.sin(currentRadian*Math.PI/180)));
canvas.drawLine(startX, startY, stopX, stopY, linePaint);
if(i%10 == 0)
canvas.drawText((int)i+"", stopX+GRADUATION_TEXT_MARGIN_TOP_X, stopY+textOffestY, anglePaint);
}
}else if(currentRadian >= 270 && currentRadian<=290){
currentRadian = 360 - currentRadian;
if(i%5 != 0){
startX = (float) (r/2 + r*Math.cos(currentRadian*Math.PI/180));
startY = (float) (r+MARGIN_TOP - r*Math.sin(currentRadian*Math.PI/180));
stopX = (float) (r/2 + (r-GRADUATION_SHORT)*Math.cos(currentRadian*Math.PI/180));
stopY = (float) (r+MARGIN_TOP - ((r-GRADUATION_SHORT)*Math.sin(currentRadian*Math.PI/180)));
canvas.drawLine(startX, startY, stopX, stopY, linePaint);
}else{
startX = (float) (r/2 + r*Math.cos(currentRadian*Math.PI/180));
startY = (float) (r+MARGIN_TOP - r*Math.sin(currentRadian*Math.PI/180));
stopX = (float) (r/2 + (r-GRADUATION_LONG)*Math.cos(currentRadian*Math.PI/180));
stopY = (float) (r+MARGIN_TOP - ((r-GRADUATION_LONG)*Math.sin(currentRadian*Math.PI/180)));
canvas.drawLine(startX, startY, stopX, stopY, linePaint);
if(i%10 == 0)
canvas.drawText((int)i+"", stopX+GRADUATION_TEXT_MARGIN_TOP_X, stopY + +textOffestY, anglePaint);
}
}
}
再画出红色指针:
canvas.drawLine(r/2, MARGIN_TOP+r, r/2, MARGIN_TOP, pointerPaint);
最后画出体重值文本。
最终实现结果:
OK,记录下方便以后回顾总结。