Android雷達(dá)圖(蜘蛛網(wǎng)圖)繪制
最近因?yàn)轫?xiàng)目需求,要實(shí)現(xiàn)一款雷達(dá)圖來表示用戶的各種成就值。
雷達(dá)圖的繪制很簡(jiǎn)單,只要思路清晰按部就班的繪制就可以了,其中使用得最多,是路徑path類的使用,使用這個(gè)類可以讓我們更加方便地繪制出正多邊形等效果。
效果圖如下:

使用方式
使用方式很簡(jiǎn)單,只要在布局文件里面,直接使用這個(gè)控件就好了,記得給它設(shè)置一個(gè)合適的具體的大小。
另外可以控制繪制的是多少邊形,通過提供的一些public方法,可以設(shè)置畫筆顏色等,當(dāng)然大家也可以按照自己的需求去修改啦。
//設(shè)置標(biāo)題public void setTitles(String[] titles) {this.titles = titles;}//設(shè)置數(shù)值public void setData(double[] data) {this.data = data;}//設(shè)置最大數(shù)值public void setMaxValue(float maxValue) {this.maxValue = maxValue;}//設(shè)置蜘蛛網(wǎng)顏色public void setMainPaintColor(int color){mainPaint.setColor(color);}//設(shè)置標(biāo)題顏色public void setTextPaintColor(int color){textPaint.setColor(color);}//設(shè)置覆蓋局域顏色public void setValuePaintColor(int color){valuePaint.setColor(color);}
具體實(shí)現(xiàn)
1、獲得布局中心
我們?cè)趏nSizeChanged(int w, int h, int oldw, int oldh)方法里面,根據(jù)View的長寬,獲取整個(gè)布局的中心坐標(biāo),因?yàn)檎麄€(gè)雷達(dá)都是以整個(gè)中心開始繪制的。
public class RadarView extends View {private int count = 6; //數(shù)據(jù)個(gè)數(shù)private float angle = (float) (Math.PI*2/count);private float radius; //網(wǎng)格最大半徑private int centerX; //中心Xprivate int centerY; //中心Yprivate String[] titles = {"a","b","c","d","e","f"};private double[] data = {100,60,60,60,100,50,10,20}; //各維度分值private float maxValue = 100; //數(shù)據(jù)最大值private Paint mainPaint; //雷達(dá)區(qū)畫筆private Paint valuePaint; //數(shù)據(jù)區(qū)畫筆private Paint textPaint; //文本畫筆...@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {radius = Math.min(h, w)/2*0.9f;//中心坐標(biāo)centerX = w/2;centerY = h/2;postInvalidate();super.onSizeChanged(w, h, oldw, oldh);}...}
2、繪制蜘蛛網(wǎng)絡(luò)
/*** 繪制正多邊形*/private void drawPolygon(Canvas canvas){Path path = new Path();float r = radius/(count-1);//r是蜘蛛絲之間的間距for(int i=1;ifloat curR = r*i;//當(dāng)前半徑path.reset();for(int j=0;jif(j==0){path.moveTo(centerX+curR,centerY);}else{//根據(jù)半徑,計(jì)算出蜘蛛絲上每個(gè)點(diǎn)的坐標(biāo)float x = (float) (centerX+curR*Math.cos(angle*j));float y = (float) (centerY+curR*Math.sin(angle*j));path.lineTo(x,y);}}path.close();//閉合路徑canvas.drawPath(path, mainPaint);}}

3、繪制從中心到末端的直線
同樣根據(jù)半徑,計(jì)算出每個(gè)末端坐標(biāo)
/*** 繪制直線*/private void drawLines(Canvas canvas){Path path = new Path();for(int i=0;ipath.reset();path.moveTo(centerX, centerY);float x = (float) (centerX+radius*Math.cos(angle*i));float y = (float) (centerY+radius*Math.sin(angle*i));path.lineTo(x, y);canvas.drawPath(path, mainPaint);}}

4、繪制文本
對(duì)于文本的繪制,首先要找到末端的坐標(biāo),由于末端和文本有一定距離,給每個(gè)末端加上這個(gè)距離以后,再繪制文本。
另外,當(dāng)文本在左邊時(shí),由于不希望文本和蜘蛛網(wǎng)交叉,我們可以先計(jì)算出文本的長度,然后使起始繪制坐標(biāo)向左偏移這個(gè)長度。
/*** 繪制文字* @param canvas*/private void drawText(Canvas canvas){Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();float fontHeight = fontMetrics.descent - fontMetrics.ascent;for(int i=0;ifloat x = (float) (centerX+(radius+fontHeight/2)*Math.cos(angle*i));float y = (float) (centerY+(radius+fontHeight/2)*Math.sin(angle*i));if(angle*i>=0&&angle*i<=Math.PI/2){//第4象限canvas.drawText(titles[i], x,y,textPaint);}else if(angle*i>=3*Math.PI/2&&angle*i<=Math.PI*2){//第3象限canvas.drawText(titles[i], x,y,textPaint);}else if(angle*i>Math.PI/2&&angle*i<=Math.PI){//第2象限float dis = textPaint.measureText(titles[i]);//文本長度canvas.drawText(titles[i], x-dis,y,textPaint);}else if(angle*i>=Math.PI&&angle*i<3*Math.PI/2){//第1象限float dis = textPaint.measureText(titles[i]);//文本長度canvas.drawText(titles[i], x-dis,y,textPaint);}}}

5、繪制覆蓋區(qū)域
覆蓋區(qū)域,只要使用path記錄下坐標(biāo)點(diǎn),然后設(shè)
valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);使path包圍區(qū)域被填充
?????/*** 繪制區(qū)域* @param canvas*/private void drawRegion(Canvas canvas){Path path = new Path();valuePaint.setAlpha(255);for(int i=0;idouble percent = data[i]/maxValue;float x = (float) (centerX+radius*Math.cos(angle*i)*percent);float y = (float) (centerY+radius*Math.sin(angle*i)*percent);if(i==0){path.moveTo(x, centerY);}else{path.lineTo(x,y);}//繪制小圓點(diǎn)canvas.drawCircle(x,y,10,valuePaint);}valuePaint.setStyle(Paint.Style.STROKE);canvas.drawPath(path, valuePaint);valuePaint.setAlpha(127);//繪制填充區(qū)域valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);canvas.drawPath(path, valuePaint);}

本篇文章主要是path類的使用,另外這個(gè)控件沒有做較好的屏幕適配,大家可以根據(jù)自己的需要修改。
到這里就結(jié)束啦。
評(píng)論
圖片
表情
