自定义View练习 - 雷达信用图表
2017-06-03 23:53
253 查看
自定义View练习 - 雷达信用图表
练习来源
Android自定义控件 芝麻信用分雷达图练习的github:https://github.com/alidili/SesameCreditScore
最终效果图
![](https://github.com/cizkey/CustomPractice/blob/master/RadarCreditChart/screenshot/screenshot01.png)
思路
绘制多边形绘制连接线
绘制填充区域
绘制总分数
绘制标题和图标
实现过程
0. 定义变量
//数据的数量 private int dataCount; //弧度 private float radian; //多边形的外接圆的半径 private int radius; //中心点x private int centerX; //中心点y private int centerY; private List<CreditBean> creditBeans; //最大分值 public int maxScore; private Paint linePaint; private Paint regionPaint; private Paint totalScorePaint; private Paint titlePaint;
1. 计算点坐标
计算坐标的示意图![](https://github.com/cizkey/CustomPractice/blob/master/RadarCreditChart/screenshot/screenshot02.png)
/** * 获得点坐标 */ public Point getPoint(int index) { return getPoint(index, 1); } /** * 获得点坐标,percent为百分比,用于获得填充区域和文字等的坐标位置. * 坐标的计算是重难点. 可以画图分析. */ public Point getPoint(int index, float percent) { int x = 0; int y = 0; if (index == 0) { x = (int) (centerX + radius * Math.sin(radian) * percent); y = (int) (centerY - radius * Math.cos(radian) * percent); } else if (index == 1) { x = (int) (centerX + radius * Math.sin(radian * 1.0f / 2) * percent); y = (int) (centerY + radius * Math.cos(radian * 1.0f / 2) * percent); } else if (index == 2) { x = (int) (centerX - radius * Math.sin(radian * 1.0f / 2) * percent); y = (int) (centerY + radius * Math.cos(radian * 1.0f / 2) * percent); } else if (index == 3) { x = (int) (centerX - radius * Math.sin(radian) * percent); y = (int) (centerY - radius * Math.cos(radian) * percent); } else if (index == 4) { x = centerX; y = (int) (centerY - radius * percent); } return new Point(x, y); }
2. 绘制过程
@Override protected void onDraw(Canvas canvas) { //绘制多边形 drawPolygon(canvas); //绘制连接线 drawLines(canvas); //绘制填充区域 drawRegion(canvas); //绘制总分数 drawTotalScore(canvas); //绘制标题和图标 drawTitleAndIcons(canvas); }
绘制多边形
这里注意需要闭合路径
/** * 绘制多边形 */ private void drawPolygon(Canvas canvas) { Path polygonPath = new Path(); for (int i = 0; i < dataCount; i++) { if (i == 0) { polygonPath.moveTo(getPoint(i).x, getPoint(i).y); } else { polygonPath.lineTo(getPoint(i).x, getPoint(i).y); } } polygonPath.close(); canvas.drawPath(polygonPath, linePaint); }
绘制连接线
直接连线从圆心到各个顶点
/** * 绘制连接线 */ private void drawLines(Canvas canvas) { for (int i = 0; i < dataCount; i++) { canvas.drawLine(centerX, centerY, getPoint(i).x, getPoint(i).y, linePaint); } }
绘制填充区域
这里的获得百分比坐标的方式可以注意下.
/** * 绘制填充区域 */ private void drawRegion(Canvas canvas) { Path regionPath = new Path(); float percent; for (int i = 0; i < creditBeans.size(); i++) { percent = creditBeans.get(i).score * 1.0f / maxScore; int x = getPoint(i, percent).x; int y = getPoint(i, percent).y; if (i == 0) { regionPath.moveTo(x, y); } else { regionPath.lineTo(x, y); } } regionPath.close(); canvas.drawPath(regionPath, regionPaint); }
绘制总分数
总分数的文字绘制在正中心.
这里要注意文字的宽度和高度的获得方式.
/** * 绘制总分数 */ private void drawTotalScore(Canvas canvas) { int totalScore = 0; for (CreditBean creditBean : creditBeans) { totalScore += creditBean.score; } //获得文字宽度 float textWidth = totalScorePaint.measureText(String.valueOf(totalScore)); Paint.FontMetrics fontMetrics = totalScorePaint.getFontMetrics(); //获得文字高度 float textHeight = Math.abs(fontMetrics.ascent) - fontMetrics.descent; canvas.drawText(String.valueOf(totalScore), centerX - textWidth / 2, centerY + textHeight / 2, totalScorePaint); }
绘制标题和图标
图标和文字位置是根据文字和图标的宽高计算的.
/** * 绘制标题和图标 */ private void drawTitleAndIcons(Canvas canvas) { for (int i = 0; i < creditBeans.size(); i++) { String title = creditBeans.get(i).title; int textX = getPoint(i, 1.2f).x; int textY = getPoint(i, 1.2f).y; //获得文字的宽高 int textWidth = (int) titlePaint.measureText(title); Paint.FontMetrics fontMetrics = titlePaint.getFontMetrics(); int textHeight = (int) (Math.abs(fontMetrics.ascent) - fontMetrics.descent); //获得图标的宽高 Bitmap icon = BitmapFactory.decodeResource(getResources(), creditBeans.get(i).icon); int iconWidth = icon.getWidth(); int iconHeight = icon.getHeight(); if (i == 0) { //不需要修正位置 } else if (i == 1) { textY += textHeight; } else if (i == 2) { textX -= textWidth; textY += textHeight; } else if (i == 3) { textX -= textWidth; } else { textX -= textWidth / 2; } int iconX = textX + textWidth / 2 - iconWidth / 2; int iconY = textY - textHeight - iconHeight - DensityUtils.dp2px(getContext(), 8); canvas.drawText(title, textX, textY, titlePaint); canvas.drawBitmap(icon, iconX, iconY, null); } }
3. 设置数据
/** * 设置数据 */ public void setData(List<CreditBean> creditBeans, int maxScore) { this.creditBeans = creditBeans; this.dataCount = creditBeans.size(); this.maxScore = maxScore; this.radian = (float) (Math.PI * 2 * 1.0f / dataCount); }
学到的知识
文字的宽度和高度的获得//获得文字宽度 float textWidth = totalScorePaint.measureText(String.valueOf(totalScore)); //获得文字高度 Paint.FontMetrics fontMetrics = totalScorePaint.getFontMetrics(); float textHeight = Math.abs(fontMetrics.ascent) - fontMetrics.descent;
获得多边形每个顶点的位置, 坐标的计算是个重点.
注意: Math.sin() 参数是弧度. 如果需要将角度转为弧度, 可以使用Math.toRadian().
计算填充区域顶点坐标和多边形的顶点是在同一条过圆心的直线上. 这里使用了percent来获得两个坐标.
/** * 获得点坐标 */ public Point getPoint(int index) { return getPoint(index, 1); } /** * 获得点坐标,percent为百分比,用于获得填充区域和文字等的坐标位置. */ public Point getPoint(int index, float percent) { int x = 0; int y = 0; if (index == 0) { x = (int) (centerX + radius * Math.sin(radian) * percent); y = (int) (centerY - radius * Math.cos(radian) * percent); } else if (index == 1) { x = (int) (centerX + radius * Math.sin(radian * 1.0f / 2) * percent); y = (int) (centerY + radius * Math.cos(radian * 1.0f / 2) * percent); } else if (index == 2) { x = (int) (centerX - radius * Math.sin(radian * 1.0f / 2) * percent); y = (int) (centerY + radius * Math.cos(radian * 1.0f / 2) * percent); } else if (index == 3) { x = (int) (centerX - radius * Math.sin(radian) * percent); y = (int) (centerY - radius * Math.cos(radian) * percent); } else if (index == 4) { x = centerX; y = (int) (centerY - radius * percent); } return new Point(x, y); }
github地址:
相关文章推荐
- Android自定义View—仿雷达扫描效果
- Android UI 之自定义RadarView——高仿微信雷达扫描
- Android自定义View实现雷达扫描动画
- Android 自定义View练习:雷达图(比重)绘制
- Android 自定义View练习:风扇吹花瓣加载中loading进度条绘制
- Android自定义View实现雷达扫描动画
- 自定义 view 练习(1):用 HorizontalScrollView 实现自定义侧滑菜单
- Android自定义图表:ChartView
- 雷达扫描之自定义view,打造最简单的自定义View
- Swift练习小demo tableView 自定义cell 简单实用
- Android 自定义View( 雷达扫描)
- 自定义View加载图片—Path和ValueAnimator的练习
- 新手自定义view练习实例之(二) 波浪view
- 自定义View练习一之图片以及标题随手势方向平滑加载
- 我的安卓回顾之旅:安卓自定义view 的练习
- 自定义view之雷达扫描
- 新手自定义view练习实例之(二) 波浪view
- Android自定义View之微信雷达
- Android UI设计之<十四>自定义ViewGroup,实现绚丽的仿支付宝咻一咻雷达脉冲效果
- 自定义View——canvas画曲线图表