有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas绘制折线图。先看看绘制的效果:

实现原理很简单,我就直接给出代码:

package com.example.testcanvasdraw;

import java.util.ArrayList;
import java.util.List;
import java.util.Random; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View; public class MyView extends View{
private int XPoint = 60;
private int YPoint = 260;
private int XScale = 8; //刻度长度
private int YScale = 40;
private int XLength = 380;
private int YLength = 240; private int MaxDataSize = XLength / XScale; private List<Integer> data = new ArrayList<Integer>(); private String[] YLabel = new String[YLength / YScale]; private Handler handler = new Handler(){
public void handleMessage(Message msg) {
if(msg.what == 0x1234){
MyView.this.invalidate();
}
};
};
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
for(int i=0; i<YLabel.length; i++){
YLabel[i] = (i + 1) + "M/s";
} new Thread(new Runnable() { @Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(data.size() >= MaxDataSize){
data.remove(0);
}
data.add(new Random().nextInt(4) + 1);
handler.sendEmptyMessage(0x1234);
}
}
}).start();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true); //去锯齿
paint.setColor(Color.BLUE); //画Y轴
canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint); //Y轴箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint-YLength + 6, paint); //箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint-YLength + 6 ,paint); //添加刻度和文字
for(int i=0; i * YScale < YLength; i++) {
canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i * YScale, paint); //刻度 canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);//文字
} //画X轴
canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint);
System.out.println("Data.size = " + data.size());
if(data.size() > 1){
for(int i=1; i<data.size(); i++){
canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) * YScale,
XPoint + i * XScale, YPoint - data.get(i) * YScale, paint);
}
}
}
}

上面绘制折线部分我们还有一种方式同样可以实现:

		if(data.size() > 1){
Path path = new Path();
path.moveTo(XPoint, YPoint - data.get(0) * YScale);
for(int i=1; i<data.size(); i++){
path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
}
canvas.drawPath(path, paint);
}

下面我们将上面代码修改,让折线下面的区域颜色填充

package com.example.testcanvasdraw;

import java.util.ArrayList;
import java.util.List;
import java.util.Random; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
/**
*
* @author 阳光小强
* http://blog.csdn.net/dawanganban
*
*/
public class MyView extends View {
private int XPoint = 60;
private int YPoint = 260;
private int XScale = 8; // 刻度长度
private int YScale = 40;
private int XLength = 380;
private int YLength = 240; private int MaxDataSize = XLength / XScale; private List<Integer> data = new ArrayList<Integer>(); private String[] YLabel = new String[YLength / YScale]; private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x1234) {
MyView.this.invalidate();
}
};
}; public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
for (int i = 0; i < YLabel.length; i++) {
YLabel[i] = (i + 1) + "M/s";
} new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (data.size() >= MaxDataSize) {
data.remove(0);
}
data.add(new Random().nextInt(4) + 1);
handler.sendEmptyMessage(0x1234);
}
}
}).start();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true); // 去锯齿
paint.setColor(Color.BLUE); // 画Y轴
canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint); // Y轴箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint - YLength
+ 6, paint); // 箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint - YLength
+ 6, paint); // 添加刻度和文字
for (int i = 0; i * YScale < YLength; i++) {
canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i
* YScale, paint); // 刻度 canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);// 文字
} // 画X轴
canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint); // 绘折线
/*
* if(data.size() > 1){ for(int i=1; i<data.size(); i++){
* canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) *
* YScale, XPoint + i * XScale, YPoint - data.get(i) * YScale, paint); }
* }
*/
paint.setStyle(Paint.Style.FILL);
if (data.size() > 1) {
Path path = new Path();
path.moveTo(XPoint, YPoint);
for (int i = 0; i < data.size(); i++) {
path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
}
path.lineTo(XPoint + (data.size() - 1) * XScale, YPoint);
canvas.drawPath(path, paint);
}
}
}

上面的效果有时候还是达不到我们的要求,我们将代码修改后效果如下:

package com.example.testcanvasdraw;

import java.util.ArrayList;
import java.util.List;
import java.util.Random; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View; /**
*
* @author 阳光小强 http://blog.csdn.net/dawanganban
*
*/
public class MyView extends View {
private int XPoint = 60;
private int YPoint = 260;
private int XScale = 8; // 刻度长度
private int YScale = 40;
private int XLength = 380;
private int YLength = 240; private int MaxDataSize = XLength / XScale; private List<Integer> data = new ArrayList<Integer>(); private String[] YLabel = new String[YLength / YScale]; private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x1234) {
MyView.this.invalidate();
}
};
}; public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
for (int i = 0; i < YLabel.length; i++) {
YLabel[i] = (i + 1) + "M/s";
} new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (data.size() >= MaxDataSize) {
data.remove(0);
}
data.add(new Random().nextInt(4) + 1);
handler.sendEmptyMessage(0x1234);
}
}
}).start();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true); // 去锯齿
paint.setColor(Color.BLUE); // 画Y轴
canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint); // Y轴箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint - YLength
+ 6, paint); // 箭头
canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint - YLength
+ 6, paint); // 添加刻度和文字
for (int i = 0; i * YScale < YLength; i++) {
canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i
* YScale, paint); // 刻度 canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);// 文字
} // 画X轴
canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint); // 绘折线
/*
* if(data.size() > 1){ for(int i=1; i<data.size(); i++){
* canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) *
* YScale, XPoint + i * XScale, YPoint - data.get(i) * YScale, paint); }
* }
*/
paint.setColor(Color.RED);
paint.setStrokeWidth(5); Paint paint2 = new Paint();
paint2.setColor(Color.BLUE);
paint2.setStyle(Paint.Style.FILL);
if (data.size() > 1) {
Path path = new Path();
Path path2 = new Path();
path.moveTo(XPoint, YPoint - data.get(0) * YScale);
path2.moveTo(XPoint, YPoint);
for (int i = 0; i < data.size(); i++) {
path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
path2.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
}
path2.lineTo(XPoint + (data.size() - 1) * XScale, YPoint);
canvas.drawPath(path, paint);
canvas.drawPath(path2, paint2);
}
}
}

感谢你对“阳光小强"的关注,我的另一篇博文很荣幸参加了CSDN举办的博文大赛,如果你觉的小强的博文对你有帮助,请为小强投上你宝贵的一票,投票地址http://vote.blog.csdn.net/Article/Details?articleid=30101091

Android自定义组件系列【9】——Canvas绘制折线图的更多相关文章

  1. Android自己定义组件系列【9】——Canvas绘制折线图

    有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了非常多插件,可是非常多时候我们须要依据详细项目自己定义这些图表,这一篇文章我们一起来看看怎样在Android中使用Can ...

  2. Android自定义控件 -Canvas绘制折线图(实现动态报表效果)

    有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas ...

  3. Android自定义组件系列【7】——进阶实践(4)

    上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...

  4. Android自定义组件系列【6】——进阶实践(3)

    上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...

  5. Android自定义组件系列【5】——进阶实践(2)

    上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...

  6. Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动

    在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...

  7. 用canvas绘制折线图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 带着canvas去流浪系列之二 绘制折线图

    [摘要] 用canvasAPI实现echarts简易图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...

  9. Android自定义组件系列【12】——非UI线程绘图SurfaceView

    一.SurfaceView的介绍 在前面我们已经会自定义View,使用canvas绘图,但是View的绘图机制存在一些缺陷. 1.View缺乏双缓冲机制. 2.程序必须重绘整个View上显示的图片,比 ...

随机推荐

  1. 【iOS与EV3混合机器人编程系列之中的一个】iOS要干嘛?EV3能够更酷!

    乐高Mindstorm EV3智能机器人(下面简称EV3)自从在2013年的CES(Consumer Electronics Show美国消费电子展)上展出之后,就吸引了全球广大机器人爱好者的眼球!E ...

  2. angularjs 合并单元格

    Html: <table class="table table-striped"> <thead> <tr> <th>国家</ ...

  3. 关于Webpack详述系列文章 (第一篇)

    WebPack官网地址(https://webpack-china.org/) 1. 什么是WebPack WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript ...

  4. C# 中 int、Convert.ToInt32()、int.Parse()的区别

    int适合简单数据类型之间的转换,C#的默认整型是int32(不支持bool型); int.Parse(string sParameter)是个构造函数,参数类型只支持string类型; Conver ...

  5. vim学习2

    进入插入模式: 在插入模式下删除: 寄存器

  6. 安装Mysql最新版本mysql-5.7.10-winx64出现的几个问题解决

    电脑是64位的安装不了Windows (x86, 32-bit),Mysql installer MSI ,然后下载了Windows (x86, 32-bit), ZIP Archive 这种是免安装 ...

  7. 洛谷 P1416 攻击火星

    P1416 攻击火星 题目描述 一群外星人将要攻击火星. 火星的地图是一个n个点的无向图.这伙外星人将按照如下方法入侵,先攻击度为0的点(相当于从图中删除掉它),然后是度为1的点,依此类推直到度为n- ...

  8. 洛谷P1876 开灯

    题目背景 该题的题目是不是感到很眼熟呢? 事实上,如果你懂的方法,该题的代码简直不能再短. 但是如果你不懂得呢?那...(自己去想) 题目描述 首先所有的灯都是关的(注意是关!),编号为1的人走过来, ...

  9. 获取input file 选中的图片,并在一个div的img里面赋值src实现预览

    代码如下利用html5实现:几乎兼容所有主流浏览器,当然IE必须是IE 6以上 [jquery代码] $(function() { $("#file_upload").change ...

  10. 查看网站使用何种框架或者技术的插件——Wappalyzer

    Wappalyzer这款插件很强大,可以查看任何网站使用的技术,包括后端语言框架和前端语言框架.还有服务器是何种类型.甚至各种版本... 插件官网:https://wappalyzer.com/