首页 > 代码库 > Android - 折线图
Android - 折线图
使用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 = http://www.mamicode.com/null;"data cannot null:"); this.data = http://www.mamicode.com/data;"间距不能为负数:" + 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 = http://www.mamicode.com/{ 0, 50, 51, 78, 200, 121, 31 };"最近一周AQI变化图"; setContentView(new BrokenLineView(this, title, null, null, data)); initView(); }
Android - 折线图
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。