经常会在游戏中看到用蜘蛛网图表达用户在游戏中的各种表现,感觉还蛮直观蛮有趣的,刚好最近也在学习自定义 View 的相关知识,就自己做一个蜘蛛网图,作为笔记了。
先放一张我感觉对自己挺有帮助,从网上找的以这个自定义 View 流程的图片
我们可以根据我们最终的效果来分析我们应该如何怎么完成这个 View。
首先可以看到最终的 View 是以整个布局的中心作为坐标原点开始绘制的,所以先要确定布局中心,然后最基础的是有几个共同中心点的正六边形,再将每个六边形的顶点与中心点相连,根据数据绘制需要覆盖的区域,最后在每个顶点旁标注文字。
整体的流程就是这样了, 可以开始写代码了
- private int count = 6; //数据个数
- private float angle = (float)(Math.PI * 2 / count);
- private float radius; //网格最大半径
- private int centerX; //中心X
- private int centerY; //中心Y
- private String[] titles = {
- "a",
- "b",
- "c",
- "d",
- "e",
- "f"
- }; //默认数据
- private double[] data = {
- 100,
- 60,
- 60,
- 60,
- 100,
- 50,
- 10,
- 20
- }; //默认分值
- private float maxValue = 100; //数据最大值
- private Paint mainPaint; //雷达区画笔
- private Paint valuePaint; //数据区画笔
- private Paint textPaint; //文本画笔
- private void init() {
- count = Math.min(data.length, titles.length);
- mainPaint = new Paint();
- mainPaint.setAntiAlias(true);
- mainPaint.setColor(Color.GRAY);
- mainPaint.setStyle(Paint.Style.STROKE);
- valuePaint = new Paint();
- valuePaint.setAntiAlias(true);
- valuePaint.setColor(Color.BLUE);
- valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);
- textPaint = new Paint();
- textPaint.setTextSize(40);
- textPaint.setStyle(Paint.Style.FILL);
- textPaint.setColor(Color.BLACK);
- }
onSizeChanged(int w, int h, int oldw, int oldh) 方法里面,根据 View 的长宽,获取整个布局的中心坐标
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- radius = Math.min(h, w) / 2 * 0.9f;
- centerX = w / 2;
- centerY = h / 2;
- postInvalidate();
- super.onSizeChanged(w, h, oldw, oldh);
- }
- private void drawPolygon(Canvas canvas) {
- Path path = new Path();
- float r = radius / (count - 1);
- for (int i = 1; i < count; i++) {
- float curR = r * i;
- path.reset();
- for (int j = 0; j < count; j++) {
- if (j == 0) {
- path.moveTo(centerX + curR, centerY);
- } else {
- 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);
- }
- }
- private void drawLines(Canvas canvas) {
- Path path = new Path();
- for (int i = 0; i < count; i++) {
- 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, mainPaint);
- }
- }
- private void drawRegion(Canvas canvas) {
- Path path = new Path();
- valuePaint.setAlpha(255);
- for (int i = 0; i < count; i++) {
- double 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);
- }
- //绘制小圆点
- canvas.drawCircle(x, y, 10, valuePaint);
- }
- valuePaint.setStyle(Paint.Style.STROKE);
- canvas.drawPath(path, valuePaint);
- valuePaint.setAlpha(127);
- //绘制填充区域
- valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);
- canvas.drawPath(path, valuePaint);
- }
对于文本的绘制,首先要找到末端的坐标,由于末端和文本有一定距离,给每个末端加上这个距离以后,再绘制文本。 另外,当文本在左边时,由于不希望文本和蜘蛛网交叉,我们可以先计算出文本的长度,然后使起始绘制坐标向左偏移这个长度。
- private void drawText(Canvas canvas) {
- Paint.FontMetrics fontMetrics = textPaint.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, textPaint);
- } else if (angle * i >= 3 * Math.PI / 2 && angle * i <= Math.PI * 2) {
- canvas.drawText(titles[i], x, y, textPaint);
- } else if (angle * i > Math.PI / 2 && angle * i <= Math.PI) {
- 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) {
- float dis = textPaint.measureText(titles[i]);
- canvas.drawText(titles[i], x - dis, y, textPaint);
- }
- }
- }
到这里就完成了蜘蛛网图的自定义 View 绘制。
来源: http://www.bubuko.com/infodetail-1966302.html