Android - 折線圖

來源:互聯網
上載者:User

標籤:

使用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;}@Overrideprotected 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中調用即可:

@Overrideprotected 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 - 折線圖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.