使用Android的canvas,画折线图:代码为:

package spt.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.util.Log;
import android.view.View; /**
* 为了扩展不同分辨率手机的兼容性,百分比和一些重要变量设置为final,其他可变变量设置为成员变量.
*
* @author Administrator
*
*/
@SuppressLint("DrawAllocation")
public class BrokenLineView extends View {
// 计算相对比例时,均使用边距margin为依照(值与比例结果成反比).
// 画轴线时,箭头所占比例.
private static final int ARROW_PECENT = 10; // x,y轴坐标点文字的比例.
private static final int X_TEXT_PECENT = 10;
private static final int Y_TEXT_PECENT = 10; // 标题文字的比例.
private static final int TITLE_TEXT_PECENT = 5; // 默认坐标轴值.
private static final String[] X_LABLE = { "a", "b", "c", "d", "e", "f", "g" };
private static final String[] Y_LABLE = { "0", "50", "100", "150", "200",
"250", "300" }; // 数据点圆的半径.
private static final int dataRadius = 10; // x,y轴坐标点数字的位置偏离轴线的距离.
private int xTextDistanceAxis = 20;
private int yTextDistanceAxis = 30; // 数据点数值文字相对于数据点的高度值.
private int dataTextAboveCircle = 25; // 边距(也不能为final,因为可能用户可能根据不同条件设置不同间距.
private int margin = 100; // X,Y轴的单位长度
private int xScale = 20;
private int yScale = 20; // 标题的高度.
private String title;
// 标题距离最顶行线的y距离.
private int titleHeight = 20;
// 原点坐标
private int x0Point;
private int y0Point; // X,Y轴上面的显示文字
private String[] xLabel = null;
private String[] yLabel = null;
// 曲线数据
private int[] data = null; public BrokenLineView(Context context, String title, String[] xLabel,
String[] yLabel, int[] data) {
super(context);
this.title = title;
// 若传递空值,则使用默认的值.
this.xLabel = (xLabel == null ? X_LABLE : xLabel);
this.yLabel = (yLabel == null ? Y_LABLE : yLabel);
if (data == null)
throw new RuntimeException("data cannot null:");
this.data = data;
} public BrokenLineView(Context context) {
this(context, null, X_LABLE, Y_LABLE, null);
} // 设置坐标原点位置和轴线上的单位长度.
public void init() {
x0Point = margin; // x0.
y0Point = getHeight() - margin; // y0.
xScale = (getWidth() - 2 * margin) / (this.xLabel.length - 1);
yScale = (getHeight() - 2 * margin) / (this.yLabel.length - 1);
} public int getMargin() {
return margin;
} public void setMargin(int margin) {
if (margin < 0)
throw new RuntimeException("间距不能为负数:" + margin);
this.margin = margin;
} @Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK); // 背景色.
Paint p = new Paint();
p.setStyle(Paint.Style.STROKE); // 设置轴线的的外框的样式“空心”(STROKE).
p.setAntiAlias(true); // 抗锯齿
p.setColor(Color.WHITE);
p.setStrokeWidth(2); // 设置轴线的的外框的宽度.
init();
drawYAxis(canvas, p);
drawXAxis(canvas, p);
drawHorizontalLine(canvas);
drawData(canvas);
} // x向线
private void drawHorizontalLine(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GRAY);
Path path = new Path();
// 先画长度为1的实线,然后长度为10的空白,再画长度为1实线,再画长度为10的空白;最后一个是是偏移量,可不理会.
PathEffect effects = new DashPathEffect(new float[] { 1, 10, 1, 10 }, 1);
paint.setPathEffect(effects);
for (int i = 1; (y0Point - i * yScale) >= margin; i++) {
int startX = x0Point;
int startY = y0Point - i * yScale;
int stopX = x0Point + (xLabel.length - 1) * xScale;
path.moveTo(startX, startY);
path.lineTo(stopX, startY);
paint.setColor(Color.DKGRAY);
canvas.drawPath(path, paint);
}
} /**
* 画y轴线
*
* @param canvas
* @param p
*/
private void drawYAxis(Canvas canvas, Paint p) {
// y轴.
canvas.drawLine(x0Point, y0Point, margin, margin, p);
// y轴箭头的左部分.
canvas.drawLine(x0Point, margin, x0Point - x0Point / ARROW_PECENT,
margin + margin / ARROW_PECENT, p);
// y轴箭头的右部分.
canvas.drawLine(x0Point, margin, x0Point + x0Point / ARROW_PECENT,
margin + margin / ARROW_PECENT, p);
} /**
* 画x轴线.
*
* @param canvas
* @param p
*/
private void drawXAxis(Canvas canvas, Paint p) {
// x轴.
canvas.drawLine(x0Point, y0Point, getWidth() - margin, y0Point, p);
// x轴箭头的上部分.
canvas.drawLine(getWidth() - margin, y0Point, getWidth() - margin
- margin / ARROW_PECENT, y0Point - margin / ARROW_PECENT, p);
// x轴箭头的下部分.
canvas.drawLine(getWidth() - margin, y0Point, getWidth() - margin
- margin / ARROW_PECENT, y0Point + margin / ARROW_PECENT, p);
} // 画数据
private void drawData(Canvas canvas) {
Paint p = new Paint();
p.setAntiAlias(true); // 抗锯齿.
p.setColor(Color.RED);
p.setTextSize(margin / X_TEXT_PECENT);
for (int x = 0; x < data.length; x++) {
int startX = x0Point + x * xScale;
// 轴坐标点文字的显示.
canvas.drawText(xLabel[x], startX, y0Point + xTextDistanceAxis, p);
// 数据点的圆.
canvas.drawCircle(startX, calY(data[x]), dataRadius, p);
// 在数据点上标数据值.
canvas.drawText(data[x] + "", startX, calY(data[x]) + dataRadius
- dataTextAboveCircle, p);
// 在数据点圆间画变化线.
// 画线时,最后数据点不执行操作.
if (x != data.length - 1)
canvas.drawLine(startX, calY(data[x]), startX + xScale,
calY(data[x + 1]), p);
} // for x. // 画y轴坐标点文字.
Paint py = new Paint();
py.setAntiAlias(true); // 抗锯齿.
py.setColor(Color.RED);
py.setTextSize(margin / Y_TEXT_PECENT);
for (int y = 0; y < yLabel.length; y++) {
int startY = y0Point - y * yScale;
// y轴坐标点文字的显示.
canvas.drawText(yLabel[y], x0Point - yTextDistanceAxis, startY, py);
} // for y. // 画标题.
Paint pTitle = new Paint();
pTitle.setAntiAlias(true); // 抗锯齿.
pTitle.setColor(Color.RED);
pTitle.setTextSize(margin / TITLE_TEXT_PECENT);
// 通过Paint.measureText计算标题长度的像素,进而将标题水平居中.
canvas.drawText(title, (getWidth() - pTitle.measureText(title)) / 2,
margin - titleHeight, pTitle);
} /**
* 计算数据值在坐标系中y的位置.
*
* @param y
* @return
*/
private int calY(int y) {
int y0 = 0;
int y1 = 0;
try {
y0 = Integer.parseInt(yLabel[0]);
y1 = Integer.parseInt(yLabel[1]);
return y0Point - ((y - y0) * yScale / (y1 - y0));
} catch (NumberFormatException e) {
Log.d("sysout", "y轴label必须是数字:" + e.getMessage());
return -1;
}
} }

然后在Activity中调用即可:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //test:
int[] data = { 0, 50, 51, 78, 200, 121, 31 };
final String title = "最近一周AQI变化图";
setContentView(new BrokenLineView(this, title, null, null, data));
initView();
}

Android - 折线图的更多相关文章

  1. Android开发学习之路-自定义控件(天气趋势折线图)

    之前写了个天气APP,带4天预报和5天历史信息.所以想着要不要加一个折线图来显示一下天气变化趋势,难得有空,就写了一下,这里做些记录,脑袋不好使容易忘事. 先放一下效果: 控件内容比较简单,就是一个普 ...

  2. Android自定义折线图

    老师布置了个作业:http://www.cnblogs.com/qingxu/p/5316897.html 作业中提到的 “玩了几天以后,大家发现了一些很有意思的现象,比如黄金点在逐渐地往下移动.” ...

  3. 最牛逼android上的图表库MpChart(二) 折线图

    最牛逼android上的图表库MpChart二 折线图 MpChart折线图介绍 MpChart折线图实例 MpChart效果 最牛逼android上的图表库MpChart(二) 折线图 最近工作中, ...

  4. android绘画折线图二

    紧接着android绘画折线图一,下面来介绍第二种方法,使用该方法,首先需要一个Androidplot-core-0.4.3-release.jar,该jar包之后也包含在项目源码中 建立一个andr ...

  5. android绘画折线图一

    最近需要实现用android来画折线图,所以百度了一下,发现确实很多,也很乱,现在整理两种方法(第二种方法在[android绘画折线图二]中实现),仅供大家参考,一起学习研究. 第一种使用ChartF ...

  6. android 自定义折线图

    看图: 比较简陋,主要是通过canvas画上去的: package com.example.democurvegraph.view; import java.util.ArrayList; impor ...

  7. Android图表引擎AChartEngine之折线图使用

    最近在帮老师做一个课题,其中app端需要显示折线图以便直观地看数据波动,上网查了些资料后发现了这款图标引擎,另外感谢李坤老师的博客,帮助很大. 废话不多说,下面写代码. 一.AChartEngine是 ...

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

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

  9. Android 自定义View -- 简约的折线图

    转载请注明出处:http://write.blog.csdn.net/postedit/50434634 接上篇 Android 圆形百分比(进度条) 自定义view 昨天分手了,不开心,来练练自定义 ...

随机推荐

  1. MVVM模式应用体会

    转自:http://www.cnblogs.com/626498301/archive/2011/04/08/2009404.html 进公司实习工作后,本人接触的第一个技术名语就是MVVM模式,从学 ...

  2. ArcServer,ArcSDE,ArcIMS,ArcEngine

    ArcServer,ArcSDE,ArcIMS,ArcEngine是ESRI的四种产品ArcGIS Server 与 ArcIMS功能相似,是将地图发布成服务供调用的ArcSDE 是空间数据引擎,是将 ...

  3. devi into python 笔记(四)python的类

    import 与 from ... import ...: #types只是一个包,FunctionType只是这个包里的一个函数.这里用它来演示 import types #如果要用Function ...

  4. centOS 下解压 rar zip 文件

    闲话不说,centos上如何安装rar.unrar在线解压缩软件呢?如果您的centos是32位的,执行如下命令: wget http://www.rarsoft.com/rar/rarlinux-3 ...

  5. JS倒计时 代码

    JS倒计时 代码 <div> <span id="KSD">3</span>天 <span id="KSH">1 ...

  6. UVA 10256 The Great Divide (凸包,多边形的位置关系)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34148 [思路] 凸包 求出红蓝点的凸包,剩下的问题就是判断两个凸 ...

  7. ActiveForm

    ActiveForm要和Model一起使用 我想在你的控制器的action中,至少应该这么写: /*action*/ $model = new Comments(); //实例化 Comments m ...

  8. 在C#中用Linq从属性文件中读取键值对Key-Value Pair

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在C#中用Linq从属性文件中读取键值对Key-Value Pair.

  9. struts2标签 遍历map集合

    首先我们来构造几个map集合.    假设如下代码 都是在ssh配置环境下搭建好,(至少struts2开发环境搭建好) (1).java 代码          下面的student对象包含的字段为 ...

  10. oppo X907刷机包 COLOROS 1.0 正式版公布 安卓4.2.2

    ROM介绍 本版本号将是X907史上最好的一版本号 全新COLOROS的UI 更新全局手势板操作 优化高速启动应用 安全保障中心也是一直採用COLOROS组成的 COLOROS 1.0给用户带来在线音 ...