使用Canvas和Paint自己绘制折线图
主要用于Canvas一个特别简单的小demo。
能够手动点击看每一个月份的数据。很easy。就是用paint在canvas上画出来的。
主要内容就是计算左边价格的位置,以下日期的位置,三根虚线的位置,五个点四根折线加价格标签的位置。
绿色价格标签是由一个圆角矩形一个三角形加一个text组成的。能够依据点击的位置在五个点上面显示。
两种方式:一种加动画一种不带动画。带动画的就是先显示五个点,然后折线从左往右显示
动画的实现是用handler不断改变须要画的折线的坐标的位置,然后一路画过去。
代码例如以下。须要的能够去github自行下载。
喜欢的请star
public class ChartView extends ImageView { /**
* 须要传入一个ChartBeanList,里面包括表格上显示的每一个点的信息。包括时间点和价格
*
*/ public static int height = 300;
public static double width = 600; private int heightReal;// 图表实际的高度
private int heightText = 70;// 底部显示时间的区域
private int heightTop = 0;// 图表上面的空白区 private int multi = 1;// 用来适配各种分辨率的机器的,为倍数
private int radi = 5 * multi;// 圆点的半径 private int widthReal;// 图表实际的宽度
private int widthText = 50 * multi;// 图表左边显示价格的区域
private int widthHead = 50;// 价格区域右边,图表左边的空白区
private int widthFoot = 25 * multi;
private int miles = 5;// 增长的毫秒数
private int px = 10;// 每毫秒添加的像素数
private boolean hasAnim = false; private double x1 = 0;
private double x2 = 0;
private double x3 = 0;
private double x4 = 0;
private double x5 = 0; private PointF p1 = new PointF();
private PointF p2 = new PointF();
private PointF p3 = new PointF();
private PointF p4 = new PointF();
private PointF p5 = new PointF();
private float p2x;
private float p3x;
private float p4x;
private float p5x;
private float p2y;
private float p3y;
private float p4y;
private float p5y;
boolean p2Init = true;
boolean isFirstRun = true;
boolean x1Complete = true;
boolean x2Complete = false;
boolean x3Complete = false;
boolean x4Complete = false;
boolean x5Complete = false;
private double min = 0d;
private double max = 100000d;
private PointF pic;
private List<ChartBean> mChartBeanList = new ArrayList<ChartBean>();
private double price;
private String unit = "元/斤";
private MyHandler handler;
private Paint p;
private float left;
private float top;
private float right;
private float bottom;
private int textWidth; public ChartView(Context context) {
super(context);
init();
} public ChartView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
} public ChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} private void init() {
handler = new MyHandler(); } public void setData(List<ChartBean> list, String unit, boolean hasAnim) {
this.mChartBeanList = list;
this.hasAnim = hasAnim;
if ("".equals(unit)) {
this.unit = unit;
}
// 4,6,2,3,5
try {
x1 = list.get(0).getPrice();
x2 = list.get(1).getPrice();
x3 = list.get(2).getPrice();
x4 = list.get(3).getPrice();
x5 = list.get(4).getPrice();
} catch (Exception e) {
e.printStackTrace();
}
max = list.get(0).getPrice();
for (int i = 0; i < list.size(); i++) {
if (max < list.get(i).getPrice()) {
max = list.get(i).getPrice();
}
}
} public void setMaxMin(double max, double min) {
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) { super.onDraw(canvas);
p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.GRAY);
p.setTypeface(Typeface.DEFAULT);
Path path = new Path(); width = canvas.getWidth();
height = canvas.getHeight();
multi = (int) Math.ceil(width / 560);
int width = canvas.getWidth();
widthText = 50 * multi;// 图表左边显示价格的区域
widthFoot = 25 * multi;
radi = 5 * multi; heightTop = 0;
heightReal = height - heightText - heightTop;
heightTop = heightReal / 4;
heightReal = height - heightText - heightTop;
widthReal = ((int) width - widthText - widthHead - widthFoot); /** 画左边的价格文字 */
p.setTextSize(17 * multi);
canvas.drawText(String.format("%.2f", (min + (max - min))), widthText - 35 * multi, heightTop, p);
canvas.drawText(String.format("%.2f", (min + (max - min) * 2 / 3)), widthText - 35 * multi, heightTop
+ heightReal / 3, p);
canvas.drawText(String.format("%.2f", (min + (max - min) / 3)), widthText - 35 * multi, heightTop + heightReal
* 2 / 3, p);
canvas.drawText(unit, widthText - 35 * multi - 5, heightTop + heightReal + 5, p);
/** 画底下的日期文字 */
try {
switch (mChartBeanList.size()) {
case 5:
canvas.drawText(mChartBeanList.get(4).getDate() + "", widthText + widthReal, 50 + heightTop
+ heightReal, p);
case 4:
canvas.drawText(mChartBeanList.get(3).getDate() + "", widthText + widthReal * 3 / 4, 50 + heightTop
+ heightReal, p);
case 3:
canvas.drawText(mChartBeanList.get(2).getDate() + "", widthText + widthReal / 2, 50 + heightTop
+ heightReal, p);
case 2:
canvas.drawText(mChartBeanList.get(1).getDate() + "", widthText + widthReal / 4, 50 + heightTop
+ heightReal, p);
case 1:
canvas.drawText(mChartBeanList.get(0).getDate() + "", widthText, 50 + heightTop + heightReal, p);
case 0:
break;
}
} catch (Exception e) {
e.printStackTrace();
} p1.x = widthText + widthHead;
p1.y = (float) (heightTop + getHeight(x1));
p2.x = widthText + widthHead + widthReal / 4;
p2.y = (float) (heightTop + getHeight(x2));
p3.x = widthText + widthHead + widthReal / 2;
p3.y = (float) (heightTop + getHeight(x3));
p4.x = widthText + widthHead + widthReal * 3 / 4;
p4.y = (float) (heightTop + getHeight(x4));
p5.x = widthText + widthHead + widthReal;
p5.y = (float) (heightTop + getHeight(x5));
if (p2Init) {
/** 初始化pp2 */
p2x = p1.x;
p2y = p1.y;
p2Init = false;
} /** 最底下的粗线 */
p.setColor(Color.GRAY);
p.setStrokeWidth(2);
canvas.drawLine(widthText, heightTop + heightReal, (float) width, heightTop + heightReal, p); /** 画三根虚线 */
p.setColor(Color.GRAY);
p.setStrokeWidth(1);
p.setStyle(Paint.Style.STROKE);
PathEffect effects = new DashPathEffect(new float[] { 5, 5, 5, 5 }, 1);
p.setPathEffect(effects);
path.moveTo(widthText, heightTop + heightReal * 2 / 3);
path.lineTo(width, heightTop + heightReal * 2 / 3);
canvas.drawPath(path, p);
path.moveTo(widthText, heightTop + heightReal / 3);
path.lineTo(width, heightTop + heightReal / 3);
canvas.drawPath(path, p);
path.moveTo(widthText, heightTop);
path.lineTo(width, heightTop);
canvas.drawPath(path, p);
p.setStyle(Paint.Style.FILL);
p.setColor(getResources().getColor(R.color.green_chart));
p.setStrokeWidth(3 * multi);
/** 几个点连起来的折线 */
try {
switch (mChartBeanList.size()) {
case 0:
break;
case 1:
canvas.drawCircle(p1.x, p1.y, radi, p);
if (pic == null) {
pic = new PointF();
pic = p1;
price = x1;
}
break;
case 2:
drawLine(canvas, p);
canvas.drawCircle(p1.x, p1.y, radi, p);
canvas.drawCircle(p2.x, p2.y, radi, p);
if (pic == null) {
pic = new PointF();
pic = p2;
price = x2;
}
break;
case 3:
drawLine(canvas, p);
canvas.drawCircle(p1.x, p1.y, radi, p);
canvas.drawCircle(p2.x, p2.y, radi, p);
canvas.drawCircle(p3.x, p3.y, radi, p);
if (pic == null) {
pic = new PointF();
pic = p3;
price = x3;
}
break;
case 4:
drawLine(canvas, p);
canvas.drawCircle(p1.x, p1.y, radi, p);
canvas.drawCircle(p2.x, p2.y, radi, p);
canvas.drawCircle(p3.x, p3.y, radi, p);
canvas.drawCircle(p4.x, p4.y, radi, p);
if (pic == null) {
pic = new PointF();
pic = p4;
price = x4;
}
break;
case 5:
drawLine(canvas, p);
canvas.drawCircle(p1.x, p1.y, radi, p);
canvas.drawCircle(p2.x, p2.y, radi, p);
canvas.drawCircle(p3.x, p3.y, radi, p);
canvas.drawCircle(p4.x, p4.y, radi, p);
canvas.drawCircle(p5.x, p5.y, radi, p);
if (pic == null) {
pic = new PointF();
pic = p5;
price = x5;
}
break;
}
} catch (Exception e) {
e.printStackTrace();
} /** 画圆角矩形 */
if (pic != null) {
// p = new Paint();
p.setAntiAlias(true);// 设置画笔的锯齿效果
p.setPathEffect(new PathEffect());
p.setColor(getResources().getColor(R.color.green_chart_dark));
textWidth = getTextWidth(p, String.format("%.2f", price));
left = pic.x - textWidth / 2;
top = pic.y - 35 * multi;
right = pic.x + textWidth / 2 + 5;
bottom = pic.y - 15 * multi;
RectF oval3 = new RectF(left, top, right, bottom);// 设置个新的长方形
canvas.drawRoundRect(oval3, 10, 10, p);// 第二个參数是x半径。第三个參数是y半径
path.moveTo(pic.x, pic.y - 5 * multi);
path.lineTo((left + right) / 2 - 5 * multi, bottom);
path.lineTo((left + right) / 2 + 5 * multi, bottom);
path.lineTo(pic.x, pic.y - 5 * multi);
canvas.drawPath(path, p);
p.setColor(Color.WHITE);
p.setTextSize(14 * multi);
canvas.drawText(String.format("%.2f", price), pic.x - textWidth / 2 + 5, pic.y - 20 * multi, p);
} if (hasAnim) {
handler.sendEmptyMessageDelayed(0, miles);
}
} public static int getTextWidth(Paint paint, String str) {
int iRet = 0;
if (str != null && str.length() > 0) {
int len = str.length();
float[] widths = new float[len];
paint.getTextWidths(str, widths);
for (int j = 0; j < len; j++) {
iRet += (int) Math.ceil(widths[j]);
}
}
return iRet;
} @Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
reFreshPic(event);
break;
case MotionEvent.ACTION_DOWN:
reFreshPic(event);
break;
case MotionEvent.ACTION_UP:
reFreshPic(event);
break;
} return super.onTouchEvent(event);
} private void reFreshPic(MotionEvent event) {
float x = event.getX();
int[] location = new int[2];
this.getLocationOnScreen(location);
float offsetX = x - widthText - widthHead;
if (offsetX < widthReal / 8) {
pic = p1;
price = x1;
} else if (offsetX > widthReal / 8 && offsetX < widthReal * 3 / 8) {
pic = p2;
price = x2;
} else if (offsetX > widthReal * 3 / 8 && offsetX < widthReal * 5 / 8) {
pic = p3;
price = x3;
} else if (offsetX > widthReal * 5 / 8 && offsetX < widthReal * 7 / 8) {
pic = p4;
price = x4;
} else if (offsetX > widthReal * 7 / 8) {
pic = p5;
price = x5;
}
this.invalidate();
} /**
* 依据传入的价格得到须要展示在view中的Y坐标
*
* max:最大值 min:最小值 height:图表的高度
*
* @param x
* @return
*/
public double getHeight(double x) {
if (max - min == 0) {
return 0;
} else {
return (max - x) / (max - min) * heightReal;
}
} public void drawLine(Canvas canvas, Paint p) {
switch (mChartBeanList.size()) {
case 0:
break;
case 1:
break;
case 2:
if (hasAnim) {
if (x1Complete) {
canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
}
} else {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
}
break;
case 3:
if (hasAnim) {
if (x1Complete) {
canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
}
if (x2Complete) {
canvas.drawLine(p2x, p2y, p3x, p3y, p);
}
} else {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
}
break;
case 4:
if (hasAnim) {
if (x1Complete) {
canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
}
if (x2Complete) {
canvas.drawLine(p2x, p2y, p3x, p3y, p);
}
if (x3Complete) {
canvas.drawLine(p3x, p3y, p4x, p4y, p);
}
} else {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
canvas.drawLine(p3.x, p3.y, p4.x, p4.y, p);
}
break;
case 5:
if (hasAnim) {
if (x1Complete) {
canvas.drawLine(p1.x, p1.y, p2x, p2y, p);
}
if (x2Complete) {
canvas.drawLine(p2x, p2y, p3x, p3y, p);
}
if (x3Complete) {
canvas.drawLine(p3x, p3y, p4x, p4y, p);
}
if (x4Complete) {
canvas.drawLine(p4x, p4y, p5x, p5y, p);
}
} else {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, p);
canvas.drawLine(p2.x, p2.y, p3.x, p3.y, p);
canvas.drawLine(p3.x, p3.y, p4.x, p4.y, p);
canvas.drawLine(p4.x, p4.y, p5.x, p5.y, p);
}
break;
}
} class MyHandler extends Handler {
public MyHandler() {
} public MyHandler(Looper L) {
super(L);
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (p2x < p2.x) {
p2x = p2x + px;
p2y = p2y + (p2.y - p1.y) / (p2.x - p1.x) * px;
// pp2.x++;
// pp2.y = pp2.y + (p2.y - p1.y) / (p2.x - p1.x) * 1;
x1Complete = true;
ChartView.this.invalidate();
p3x = p2x;
System.out.println("p2y--" + p2y);
p3y = p2y;
} else if (p3x < p3.x) {
p3x = p3x + px;
p3y = p3y + (p3.y - p2.y) / (p3.x - p2.x) * px;
System.out.println("2");
// pp3.x = pp3.x + 1;
// pp3.y = pp3.y + (p3.y - p2.y) / (p3.x - p2.x) * 1;
ChartView.this.invalidate();
x2Complete = true;
p4x = p3x;
p4y = p3y;
} else if (p4x < p4.x) {
System.out.println("3");
p4x = p4x + px;
p4y = p4y + (p4.y - p3.y) / (p4.x - p3.x) * px;
// pp4.x = pp4.x + 1;
// pp4.y = pp4.y + (p4.y - p3.y) / (p4.x - p3.x) * 1;
ChartView.this.invalidate();
x3Complete = true;
p5x = p4x;
p5y = p4y;
} else if (p5x < p5.x) {
p5x = p5x + px;
System.out.println("4");
p5y = p5y + (p5.y - p4.y) / (p5.x - p4.x) * px;
// pp5.x = pp5.x + 1;
// pp5.y = pp5.y + (p5.y - p4.y) / (p5.x - p4.x) * 1;
ChartView.this.invalidate();
x4Complete = true;
} else {
System.out.println("return");
return;
}
}
}
}
https://github.com/yocn/chartView
版权声明:本文博客原创文章,博客,未经同意,不得转载。
使用Canvas和Paint自己绘制折线图的更多相关文章
- Android自己定义组件系列【9】——Canvas绘制折线图
有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了非常多插件,可是非常多时候我们须要依据详细项目自己定义这些图表,这一篇文章我们一起来看看怎样在Android中使用Can ...
- Android自定义控件 -Canvas绘制折线图(实现动态报表效果)
有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas ...
- Android自定义组件系列【9】——Canvas绘制折线图
有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas ...
- 用canvas绘制折线图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【带着canvas去流浪】(2)绘制折线图
目录 一. 任务说明 二. 重点提示 三. 示例代码 3.1 一般折线图 3.2 用贝塞尔曲线绘制平滑折线图 四. 大数据量场景 示例代码托管在:https://github.com/dashnowo ...
- 带着canvas去流浪系列之二 绘制折线图
[摘要] 用canvasAPI实现echarts简易图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...
- 【Canvas】(2)---绘制折线图
绘制折线图 之前在工作的时候,用过百度的ECharts绘制折线图,上手很简单,这里通过canvas绘制一个简单的折线图.这里将一整个绘制过程分为几个步骤: 1.绘制网格 2.绘制坐标系 3.绘制点 4 ...
- html5绘制折线图
html5绘制折线图详细代码 <html> <canvas id="a_canvas" width="1000" height="7 ...
- php中用GD绘制折线图
php中用GD绘制折线图,代码如下: Class Chart{ private $image; // 定义图像 private $title; // 定义标题 private $ydata; // 定 ...
随机推荐
- Ubuntu--有关VMware Tools安装问题
虚拟机中找不到VMware Tools选项 在虚拟机上安装了ubuntu系统后,是不可以进行系统间数据共享的,也就是说我win7系统里的文件,不能拷贝到虚拟机的ubuntu系统. 解决方案:我们需要安 ...
- Hibernate常用Annotation标签说明
@ javax.persistence.Entity 实体类定义,该标签表示当前类是一个Hibernate的数据库实体,对应着数据库中的某个表 位置:用于类级别 参数:无 样例:@Entity 注意: ...
- java 类 及其 执行过程
java 类 命名 java类文件中 只能有一个公开类 且 公开类类名与当前类文件的文件名一致 方法如果使用了static修饰,那么此方法是类方法,可以 类名.方法名 使用. 你的main方法在同 ...
- CSDN-markdown语法之怎样使用LaTeX语法编写数学公式
文件夹 文件夹 正文 标记公式 行内公式 块级公式 上标和下标 分数表示 各种括号 根号表示 省略号 矢量表示 间隔空间 希腊字母 特殊字符 关系运算符 集合运算符 对数运算符 三角运算符 微积分运算 ...
- 使用Socket沟通
当两台电脑TCP/IP协议进行通讯.平时Socket对象来表示该通信接口的两端,并通过Socket生产I/O流进行网络通信. 其中ServerSocket对象可以接收从连接的其他通信实体的请求.这个目 ...
- NET MVC运行机制
[图解ASP.NET MVC运行机制理解-简易版] 很多盆友咨询ASP.NET MVC的机制.网上也有好多.但是都是相当深奥.看的云里雾里的.我今天抽空,整理个简易版本.把处理流程走一遍. 当然, ...
- 搭建solr单机版
solr单机版的搭建 一.solr单机版的搭建 1.运行环境 solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jetty(ja),本教va写 ...
- Win 10开门人类智慧的世界领先
3月18日,从微软硬件project大会(WinHEC 2015)上传来好消息:今年夏天,Win 10将要正式公布.Win 10公布,有何新意? 微软新领导人纳德拉(Nadella)主张:运计算,大数 ...
- [Windows Phone] 地图覆叠层控制项(MapOverlay )
原文:[Windows Phone] 地图覆叠层控制项(MapOverlay ) 前言 当使用地图时,我们可能需要定位一些座标图示或是绘制一些文字线条,这时可以在地图上加上覆叠层进行绘制,在 Wind ...
- 如何利用多核CPU来加速你的Linux命令 — awk, sed, bzip2, grep, wc等(转)
你是否曾经有过要计算一个非常大的数据(几百GB)的需求?或在里面搜索,或其它操作——一些无法并行的操作.数据专家们,我是在对你们说.你可能有一个4核或更多核的CPU,但我们合适的工具,例如 grep, ...