android 手把手教你自定义view(一)--雷达图模仿
1.先看一下我们要绘制的目标图
思路:
1.绘制多边形
2.绘制顶点文字
3.绘制覆盖区域
(一)绘制多边形
/** * 自定义雷达view * @author DEV-81 * @version 1.0 */ public class CustomRadarView extends View{ private Paint mPaint; //多边形边框 private int centerX=0; private int centerY=0; private int count=6;//多边形的个数 private Path mPath;//绘制多边形的path private float radius=0;//半径 private float currentR=0;//是蜘蛛丝之间的间距 //正多边形两条边的夹角 private float angle = (float) (Math.PI*2/count); public CustomRadarView(Context context) { this(context,null); } public CustomRadarView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } /** * 初始化 * */ private void init() { mPaint=new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); mPaint.setStrokeWidth(1); mPath=new Path(); } /** * 获取view的宽和高,并做相关的设置 * */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { centerX=w/2; centerY=h/2; radius = Math.min(h, w)/2*0.8f; invalidate(); super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawPolygon(canvas); } /** * 绘制多边形 * @param canvas * */ private void drawPolygon(Canvas canvas) { // 是蜘蛛丝之间的间距 currentR=radius/(count-1); for (int i = 0; i < count; i++) { //获取每一个多边形外切圆的半径 float r=currentR*i; mPath.reset(); //绘制一个多边形的多条边 for (int j = 0; j < count; j++) { if(j==0){ //每一圈设置起点 mPath.moveTo(centerX+r,centerY); }else{ //根据半径,计算出蜘蛛丝上每个点的坐标 float x= (float) (centerX+r*Math.cos(angle*j)); float y= (float) (centerY+r*Math.sin(angle*j)); mPath.lineTo(x,y); } } mPath.close(); canvas.drawPath(mPath,mPaint); } } }
显示效果如下:
接下来需要绘制中心到末端的直线
/** * 绘制中心到多边形的各个顶点的连线 * @param canvas * */ private void drawLines(Canvas canvas) { Path path=new Path(); for (int i = 0; i < count; i++) { //每一次重置path,将起点移到中心 path.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,mPaint); } }
绘制顶端文字
/** * 绘制文字 * @param canvas * */ private void drawText(Canvas canvas) { Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); float fontHeight = fontMetrics.descent - fontMetrics.ascent; for (int i = 0; i < count; i++) { float 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){ //第四象限 //文字绘制在顶点的右边 canvas.drawText(titles[i],x,y,mTextPaint); }else if(angle*i>Math.PI/2 && angle*i<=Math.PI){ //第三象限 //文字绘制在顶点的左边 ,也就是顶点坐标然后像左侧偏移一部分距离 float offset = mTextPaint.measureText(titles[i]); canvas.drawText(titles[i],x-offset,y,mTextPaint); }else if(angle*i>Math.PI && angle*i<=3*Math.PI/2){ //第二象限 //文字绘制在顶点的左边 ,也就是顶点坐标然后像左侧偏移一部分距离 float offset = mTextPaint.measureText(titles[i]); canvas.drawText(titles[i],x-offset,y,mTextPaint); }else if(angle*i>3*Math.PI/2 && angle*i<2*Math.PI){//第一象限 //文字绘制在顶点的右边 canvas.drawText(titles[i],x,y,mTextPaint); } } }
效果图如下:
知识点扩展:
1.在android 中坐标系与数学中坐标系的区别: