最近项目里要做一个简单的曲线图来标识数据,开始以为很简单,android已经有那么多的开源图表库了,什么achartenginee,hellochart,mpandroidchart等等,下载Demo一找,都强大到有点不适合我这个小小的展示功能了,直是无语了。于是只能自已去画了,继承自View去重绘。
下面先看一下效果图:
思路:根据点的数量将Canvas等分,等分后先绘制图表的所有横轴和纵轴。再将数据转化为点坐标,绘制到屏幕上,最后将相邻两点连成线即可。
源码如下:
import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.Point; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager; /********************************************************** * @文件名称:LineGraphicView.java * @文件作者:rzq * @创建时间:2015年5月27日 下午3:05:19 * @文件描述:自定义简单曲线图 * @修改历史:2015年5月27日创建初始版本 **********************************************************/ class LineGraphicView extends View { /** * 公共部分 */ private static final int CIRCLE_SIZE = 10; private static enum Linestyle { Line, Curve } private Context mContext; private Paint mPaint; private Resources res; private DisplayMetrics dm; /** * data */ private Linestyle mStyle = Linestyle.Curve; private int canvasHeight; private int canvasWidth; private int bheight = 0; private int blwidh; private boolean isMeasure = true; /** * Y轴最大值 */ private int maxValue; /** * Y轴间距值 */ private int averageValue; private int marginTop = 20; private int marginBottom = 40; /** * 曲线上总点数 */ private Point[] mPoints; /** * 纵坐标值 */ private ArrayList<Double> yRawData; /** * 横坐标值 */ private ArrayList<String> xRawDatas; private ArrayList<Integer> xList = new ArrayList<Integer>();// 记录每个x的值 private int spacingHeight; public LineGraphicView(Context context) { this(context, null); } public LineGraphicView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; initView(); } private void initView() { this.res = mContext.getResources(); this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dm = new DisplayMetrics(); WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(dm); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (isMeasure) { this.canvasHeight = getHeight(); this.canvasWidth = getWidth(); if (bheight == 0) bheight = (int) (canvasHeight - marginBottom); blwidh = dip2px(30); isMeasure = false; } } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(res.getColor(R.color.color_f2f2f2)); drawAllXLine(canvas); // 画直线(纵向) drawAllYLine(canvas); // 点的操作设置 mPoints = getPoints(); mPaint.setColor(res.getColor(R.color.color_ff4631)); mPaint.setStrokeWidth(dip2px(2.5f)); mPaint.setStyle(Style.STROKE); if (mStyle == Linestyle.Curve) { drawScrollLine(canvas); } else { drawLine(canvas); } mPaint.setStyle(Style.FILL); for (int i = 0; i < mPoints.length; i++) { canvas.drawCircle(mPoints[i].x, mPoints[i].y, CIRCLE_SIZE / 2, mPaint); } } /** * 画所有横向表格,包括X轴 */ private void drawAllXLine(Canvas canvas) { for (int i = 0; i < spacingHeight + 1; i++) { canvas.drawLine(blwidh, bheight - (bheight / spacingHeight) * i + marginTop, (canvasWidth - blwidh), bheight - (bheight / spacingHeight) * i + marginTop, mPaint);// Y坐标 drawText(String.valueOf(averageValue * i), blwidh / 2, bheight - (bheight / spacingHeight) * i + marginTop, canvas); } } /** * 画所有纵向表格,包括Y轴 */ private void drawAllYLine(Canvas canvas) { for (int i = 0; i < yRawData.size(); i++) { xList.add(blwidh + (canvasWidth - blwidh) / yRawData.size() * i); canvas.drawLine(blwidh + (canvasWidth - blwidh) / yRawData.size() * i, marginTop, blwidh + (canvasWidth - blwidh) / yRawData.size() * i, bheight + marginTop, mPaint); drawText(xRawDatas.get(i), blwidh + (canvasWidth - blwidh) / yRawData.size() * i, bheight + dip2px(26), canvas);// X坐标 } } private void drawScrollLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; int wt = (startp.x + endp.x) / 2; Point p3 = new Point(); Point p4 = new Point(); p3.y = startp.y; p3.x = wt; p4.y = endp.y; p4.x = wt; Path path = new Path(); path.moveTo(startp.x, startp.y); path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y); canvas.drawPath(path, mPaint); } } private void drawLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mPaint); } } private void drawText(String text, int x, int y, Canvas canvas) { Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setTextSize(dip2px(12)); p.setColor(res.getColor(R.color.color_999999)); p.setTextAlign(Paint.Align.LEFT); canvas.drawText(text, x, y, p); } private Point[] getPoints() { Point[] points = new Point[yRawData.size()]; for (int i = 0; i < yRawData.size(); i++) { int ph = bheight - (int) (bheight * (yRawData.get(i) / maxValue)); points[i] = new Point(xList.get(i), ph + marginTop); } return points; } public void setData(ArrayList<Double> yRawData, ArrayList<String> xRawData, int maxValue, int averageValue) { this.maxValue = maxValue; this.averageValue = averageValue; this.mPoints = new Point[yRawData.size()]; this.xRawDatas = xRawData; this.yRawData = yRawData; this.spacingHeight = maxValue / averageValue; } public void setTotalvalue(int maxValue) { this.maxValue = maxValue; } public void setPjvalue(int averageValue) { this.averageValue = averageValue; } public void setMargint(int marginTop) { this.marginTop = marginTop; } public void setMarginb(int marginBottom) { this.marginBottom = marginBottom; } public void setMstyle(Linestyle mStyle) { this.mStyle = mStyle; } public void setBheight(int bheight) { this.bheight = bheight; } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ private int dip2px(float dpValue) { return (int) (dpValue * dm.density + 0.5f); } }
package com.example; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { LineGraphicView tu; ArrayList<Double> yList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tu = (LineGraphicView) findViewById(R.id.line_graphic); yList = new ArrayList<Double>(); yList.add((double) 2.103); yList.add(4.05); yList.add(6.60); yList.add(3.08); yList.add(4.32); yList.add(2.0); yList.add(5.0); ArrayList<String> xRawDatas = new ArrayList<String>(); xRawDatas.add("05-19"); xRawDatas.add("05-20"); xRawDatas.add("05-21"); xRawDatas.add("05-22"); xRawDatas.add("05-23"); xRawDatas.add("05-24"); xRawDatas.add("05-25"); xRawDatas.add("05-26"); tu.setData(yList, xRawDatas, 8, 2); } }
原文地址:http://blog.csdn.net/lcq5211314123/article/details/46122907