欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿支付宝上芝麻信用分雷达图

程序员文章站 2024-03-05 10:27:12
一、首先看下支付宝上芝麻信用分的效果图: 二、思路      1、确定雷达图中心点坐标   &nb...

一、首先看下支付宝上芝麻信用分的效果图:

Android仿支付宝上芝麻信用分雷达图

二、思路

     1、确定雷达图中心点坐标

     2、绘制多边形及连接线

     3、根据维度值绘制覆盖区域

     4、绘制分数

     5、绘制每个维度的标题文字和图标

三、实现

获取布局的中心坐标

onsizechanged(int w, int h, int oldw, int oldh)方法里面,根据view的长宽,计算出雷达图的半径(这里取布局宽高最小值的四分之一,可以自定义),获取整个布局的中心坐标。

public class creditscoreview extends view {

 //数据个数
 private int datacount = 5;
 //每个角的弧度
 private float radian = (float) (math.pi * 2 / datacount);
 //雷达图半径
 private float radius;
 //中心x坐标
 private int centerx;
 //中心y坐标
 private int centery;
 //各维度标题
 private string[] titles = {"履约能力", "信用历史", "人脉关系", "行为偏好", "身份特质"};
 //各维度图标
 private int[] icons = {r.mipmap.ic_performance, r.mipmap.ic_history, r.mipmap.ic_contacts,
   r.mipmap.ic_predilection, r.mipmap.ic_identity};
 //各维度分值
 private float[] data = {170, 180, 160, 170, 180};
 //数据最大值
 private float maxvalue = 190;
 //雷达图与标题的间距
 private int radarmargin = densityutils.dp2px(getcontext(), 15);
 //雷达区画笔
 private paint mainpaint;
 //数据区画笔
 private paint valuepaint;
 //分数画笔
 private paint scorepaint;
 //标题画笔
 private paint titlepaint;
 //图标画笔
 private paint iconpaint;
 //分数大小
 private int scoresize = densityutils.dp2px(getcontext(), 28);
 //标题文字大小
 private int titlesize = densityutils.dp2px(getcontext(), 13);

 ...

 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
  //雷达图半径
  radius = math.min(h, w) / 2 * 0.5f;
  //中心坐标
  centerx = w / 2;
  centery = h / 2;
  postinvalidate();
  super.onsizechanged(w, h, oldw, oldh);
 }

 ...
}

绘制多边形和连接线

主要看下getpoint方法,此方法封装了获取雷达图上各个点坐标的计算逻辑。

/**
 * 绘制多边形
 *
 * @param canvas 画布
 */
private void drawpolygon(canvas canvas) {
 path path = new path();
 for (int i = 0; i < datacount; i++) {
  if (i == 0) {
   path.moveto(getpoint(i).x, getpoint(i).y);
  } else {
   path.lineto(getpoint(i).x, getpoint(i).y);
  }
 }

 //闭合路径
 path.close();
 canvas.drawpath(path, mainpaint);
}

/**
 * 绘制连接线
 *
 * @param canvas 画布
 */
private void drawlines(canvas canvas) {
 path path = new path();
 for (int i = 0; i < datacount; i++) {
  path.reset();
  path.moveto(centerx, centery);
  path.lineto(getpoint(i).x, getpoint(i).y);
  canvas.drawpath(path, mainpaint);
 }
}

getpoint方法,参数radarmarginpercent在此步骤赋予默认值。

/**
 * 获取雷达图上各个点的坐标
 *
 * @param position 坐标位置(右上角为0,顺时针递增)
 * @return 坐标
 */
private point getpoint(int position) {
 return getpoint(position, 0, 1);
}

/**
 * 获取雷达图上各个点的坐标(包括维度标题与图标的坐标)
 *
 * @param position 坐标位置
 * @param radarmargin 雷达图与维度标题的间距
 * @param percent  覆盖区的的百分比
 * @return 坐标
 */
private point getpoint(int position, int radarmargin, float percent) {
 int x = 0;
 int y = 0;

 if (position == 0) {
  x = (int) (centerx + (radius + radarmargin) * math.sin(radian) * percent);
  y = (int) (centery - (radius + radarmargin) * math.cos(radian) * percent);

 } else if (position == 1) {
  x = (int) (centerx + (radius + radarmargin) * math.sin(radian / 2) * percent);
  y = (int) (centery + (radius + radarmargin) * math.cos(radian / 2) * percent);

 } else if (position == 2) {
  x = (int) (centerx - (radius + radarmargin) * math.sin(radian / 2) * percent);
  y = (int) (centery + (radius + radarmargin) * math.cos(radian / 2) * percent);

 } else if (position == 3) {
  x = (int) (centerx - (radius + radarmargin) * math.sin(radian) * percent);
  y = (int) (centery - (radius + radarmargin) * math.cos(radian) * percent);

 } else if (position == 4) {
  x = centerx;
  y = (int) (centery - (radius + radarmargin) * percent);
 }

 return new point(x, y);
}

Android仿支付宝上芝麻信用分雷达图
多边形和连接线

绘制覆盖区域

/**
 * 绘制覆盖区域
 *
 * @param canvas 画布
 */
private void drawregion(canvas canvas) {
 path path = new path();

 for (int i = 0; i < datacount; i++) {
  //计算百分比
  float percent = data[i] / maxvalue;
  int x = getpoint(i, 0, percent).x;
  int y = getpoint(i, 0, percent).y;
  if (i == 0) {
   path.moveto(x, y);
  } else {
   path.lineto(x, y);
  }
 }

 //绘制填充区域的边界
 path.close();
 valuepaint.setstyle(paint.style.stroke);
 canvas.drawpath(path, valuepaint);

 //绘制填充区域
 valuepaint.setstyle(paint.style.fill_and_stroke);
 canvas.drawpath(path, valuepaint);
}

Android仿支付宝上芝麻信用分雷达图
覆盖区域

绘制分数

/**
 * 绘制分数
 *
 * @param canvas 画布
 */
private void drawscore(canvas canvas) {
 int score = 0;
 //计算总分
 for (int i = 0; i < datacount; i++) {
  score += data[i];
 }
 canvas.drawtext(score + "", centerx, centery + scoresize / 2, scorepaint);
}

Android仿支付宝上芝麻信用分雷达图
分数

绘制标题

/**
 * 绘制标题
 *
 * @param canvas 画布
 */
private void drawtitle(canvas canvas) {
 for (int i = 0; i < datacount; i++) {
  int x = getpoint(i, radarmargin, 1).x;
  int y = getpoint(i, radarmargin, 1).y;

  bitmap bitmap = bitmapfactory.decoderesource(getresources(), icons[i]);
  int iconheight = bitmap.getheight();
  float titlewidth = titlepaint.measuretext(titles[i]);

  //底下两个角的坐标需要向下移动半个图片的位置(1、2)
  if (i == 1) {
   y += (iconheight / 2);
  } else if (i == 2) {
   x -= titlewidth;
   y += (iconheight / 2);
  } else if (i == 3) {
   x -= titlewidth;
  } else if (i == 4) {
   x -= titlewidth / 2;
  }
  canvas.drawtext(titles[i], x, y, titlepaint);
 }
}

Android仿支付宝上芝麻信用分雷达图
标题

绘制图标

/**
 * 绘制图标
 *
 * @param canvas 画布
 */
private void drawicon(canvas canvas) {
 for (int i = 0; i < datacount; i++) {
  int x = getpoint(i, radarmargin, 1).x;
  int y = getpoint(i, radarmargin, 1).y;

  bitmap bitmap = bitmapfactory.decoderesource(getresources(), icons[i]);
  int iconwidth = bitmap.getwidth();
  int iconheight = bitmap.getheight();
  float titlewidth = titlepaint.measuretext(titles[i]);

  //上面获取到的x、y坐标是标题左下角的坐标
  //需要将图标移动到标题上方居中位置
  if (i == 0) {
   x += (titlewidth - iconwidth) / 2;
   y -= (iconheight + gettextheight(titlepaint));
  } else if (i == 1) {
   x += (titlewidth - iconwidth) / 2;
   y -= (iconheight / 2 + gettextheight(titlepaint));
  } else if (i == 2) {
   x -= (iconwidth + (titlewidth - iconwidth) / 2);
   y -= (iconheight / 2 + gettextheight(titlepaint));
  } else if (i == 3) {
   x -= (iconwidth + (titlewidth - iconwidth) / 2);
   y -= (iconheight + gettextheight(titlepaint));
  } else if (i == 4) {
   x -= iconwidth / 2;
   y -= (iconheight + gettextheight(titlepaint));
  }

  canvas.drawbitmap(bitmap, x, y, titlepaint);
 }
}
/**
 * 获取文本的高度
 *
 * @param paint 文本绘制的画笔
 * @return 文本高度
 */
private int gettextheight(paint paint) {
 paint.fontmetrics fontmetrics = paint.getfontmetrics();
 return (int) (fontmetrics.descent - fontmetrics.ascent);
}

Android仿支付宝上芝麻信用分雷达图
图标

总结

好了,到这里主要的绘制工作就完成了,有些图标实在找不到,就用相似的代替了。希望这篇文章的内容对各位android开发者们能有所帮助,如果有疑问大家可以留言交流。