android自定义View之曲线图

最近项目里要做一个简单的曲线图来标识数据,开始以为很简单,android已经有那么多的开源图表库了,什么achartenginee,hellochart,mpandroidchart等等,下载Demo一找,都强大到有点不适合我这个小小的展示功能了,直是无语了。于是只能自已去画了,继承自View去重绘。

 下面先看一下效果图:

    

   思路:根据点的数量将Canvas等分,等分后先绘制图表的所有横轴和纵轴。再将数据转化为点坐标,绘制到屏幕上,最后将相邻两点连成线即可。

 源码如下:

[java]  view plain copy
  1. import android.content.Context;  
  2. import android.content.res.Resources;  
  3. import android.graphics.Canvas;  
  4. import android.graphics.Paint;  
  5. import android.graphics.Paint.Style;  
  6. import android.graphics.Path;  
  7. import android.graphics.Point;  
  8. import android.util.AttributeSet;  
  9. import android.util.DisplayMetrics;  
  10. import android.view.View;  
  11. import android.view.WindowManager;  
  12.   
  13. /********************************************************** 
  14.  * @文件名称:LineGraphicView.java 
  15.  * @文件作者:rzq 
  16.  * @创建时间:2015年5月27日 下午3:05:19 
  17.  * @文件描述:自定义简单曲线图 
  18.  * @修改历史:2015年5月27日创建初始版本 
  19.  **********************************************************/  
  20. class LineGraphicView extends View  
  21. {  
  22.     /** 
  23.      * 公共部分 
  24.      */  
  25.     private static final int CIRCLE_SIZE = 10;  
  26.   
  27.     private static enum Linestyle  
  28.     {  
  29.         Line, Curve  
  30.     }  
  31.   
  32.     private Context mContext;  
  33.     private Paint mPaint;  
  34.     private Resources res;  
  35.     private DisplayMetrics dm;  
  36.   
  37.     /** 
  38.      * data 
  39.      */  
  40.     private Linestyle mStyle = Linestyle.Curve;  
  41.   
  42.     private int canvasHeight;  
  43.     private int canvasWidth;  
  44.     private int bheight = 0;  
  45.     private int blwidh;  
  46.     private boolean isMeasure = true;  
  47.     /** 
  48.      * Y轴最大值 
  49.      */  
  50.     private int maxValue;  
  51.     /** 
  52.      * Y轴间距值 
  53.      */  
  54.     private int averageValue;  
  55.     private int marginTop = 20;  
  56.     private int marginBottom = 40;  
  57.   
  58.     /** 
  59.      * 曲线上总点数 
  60.      */  
  61.     private Point[] mPoints;  
  62.     /** 
  63.      * 纵坐标值 
  64.      */  
  65.     private ArrayList<Double> yRawData;  
  66.     /** 
  67.      * 横坐标值 
  68.      */  
  69.     private ArrayList<String> xRawDatas;  
  70.     private ArrayList<Integer> xList = new ArrayList<Integer>();// 记录每个x的值  
  71.     private int spacingHeight;  
  72.   
  73.     public LineGraphicView(Context context)  
  74.     {  
  75.         this(context, null);  
  76.     }  
  77.   
  78.     public LineGraphicView(Context context, AttributeSet attrs)  
  79.     {  
  80.         super(context, attrs);  
  81.         this.mContext = context;  
  82.         initView();  
  83.     }  
  84.   
  85.     private void initView()  
  86.     {  
  87.         this.res = mContext.getResources();  
  88.         this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  89.         dm = new DisplayMetrics();  
  90.         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);  
  91.         wm.getDefaultDisplay().getMetrics(dm);  
  92.     }  
  93.   
  94.     @Override  
  95.     protected void onSizeChanged(int w, int h, int oldw, int oldh)  
  96.     {  
  97.         if (isMeasure)  
  98.         {  
  99.             this.canvasHeight = getHeight();  
  100.             this.canvasWidth = getWidth();  
  101.             if (bheight == 0)  
  102.                 bheight = (int) (canvasHeight - marginBottom);  
  103.             blwidh = dip2px(30);  
  104.             isMeasure = false;  
  105.         }  
  106.     }  
  107.   
  108.     @Override  
  109.     protected void onDraw(Canvas canvas)  
  110.     {  
  111.         mPaint.setColor(res.getColor(R.color.color_f2f2f2));  
  112.   
  113.         drawAllXLine(canvas);  
  114.         // 画直线(纵向)  
  115.         drawAllYLine(canvas);  
  116.         // 点的操作设置  
  117.         mPoints = getPoints();  
  118.   
  119.         mPaint.setColor(res.getColor(R.color.color_ff4631));  
  120.         mPaint.setStrokeWidth(dip2px(2.5f));  
  121.         mPaint.setStyle(Style.STROKE);  
  122.         if (mStyle == Linestyle.Curve)  
  123.         {  
  124.             drawScrollLine(canvas);  
  125.         }  
  126.         else  
  127.         {  
  128.             drawLine(canvas);  
  129.         }  
  130.   
  131.         mPaint.setStyle(Style.FILL);  
  132.         for (int i = 0; i < mPoints.length; i++)  
  133.         {  
  134.             canvas.drawCircle(mPoints[i].x, mPoints[i].y, CIRCLE_SIZE / 2, mPaint);  
  135.         }  
  136.     }  
  137.   
  138.     /** 
  139.      *  画所有横向表格,包括X轴 
  140.      */  
  141.     private void drawAllXLine(Canvas canvas)  
  142.     {  
  143.         for (int i = 0; i < spacingHeight + 1; i++)  
  144.         {  
  145.             canvas.drawLine(blwidh, bheight - (bheight / spacingHeight) * i + marginTop, (canvasWidth - blwidh),  
  146.                     bheight - (bheight / spacingHeight) * i + marginTop, mPaint);// Y坐标  
  147.             drawText(String.valueOf(averageValue * i), blwidh / 2, bheight - (bheight / spacingHeight) * i + marginTop,  
  148.                     canvas);  
  149.         }  
  150.     }  
  151.   
  152.     /** 
  153.      * 画所有纵向表格,包括Y轴  
  154.      */  
  155.     private void drawAllYLine(Canvas canvas)  
  156.     {  
  157.         for (int i = 0; i < yRawData.size(); i++)  
  158.         {  
  159.             xList.add(blwidh + (canvasWidth - blwidh) / yRawData.size() * i);  
  160.             canvas.drawLine(blwidh + (canvasWidth - blwidh) / yRawData.size() * i, marginTop, blwidh  
  161.                     + (canvasWidth - blwidh) / yRawData.size() * i, bheight + marginTop, mPaint);  
  162.             drawText(xRawDatas.get(i), blwidh + (canvasWidth - blwidh) / yRawData.size() * i, bheight + dip2px(26),  
  163.                     canvas);// X坐标  
  164.         }  
  165.     }  
  166.   
  167.     private void drawScrollLine(Canvas canvas)  
  168.     {  
  169.         Point startp = new Point();  
  170.         Point endp = new Point();  
  171.         for (int i = 0; i < mPoints.length - 1; i++)  
  172.         {  
  173.             startp = mPoints[i];  
  174.             endp = mPoints[i + 1];  
  175.             int wt = (startp.x + endp.x) / 2;  
  176.             Point p3 = new Point();  
  177.             Point p4 = new Point();  
  178.             p3.y = startp.y;  
  179.             p3.x = wt;  
  180.             p4.y = endp.y;  
  181.             p4.x = wt;  
  182.   
  183.             Path path = new Path();  
  184.             path.moveTo(startp.x, startp.y);  
  185.             path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);  
  186.             canvas.drawPath(path, mPaint);  
  187.         }  
  188.     }  
  189.   
  190.     private void drawLine(Canvas canvas)  
  191.     {  
  192.         Point startp = new Point();  
  193.         Point endp = new Point();  
  194.         for (int i = 0; i < mPoints.length - 1; i++)  
  195.         {  
  196.             startp = mPoints[i];  
  197.             endp = mPoints[i + 1];  
  198.             canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mPaint);  
  199.         }  
  200.     }  
  201.   
  202.     private void drawText(String text, int x, int y, Canvas canvas)  
  203.     {  
  204.         Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);  
  205.         p.setTextSize(dip2px(12));  
  206.         p.setColor(res.getColor(R.color.color_999999));  
  207.         p.setTextAlign(Paint.Align.LEFT);  
  208.         canvas.drawText(text, x, y, p);  
  209.     }  
  210.   
  211.     private Point[] getPoints()  
  212.     {  
  213.         Point[] points = new Point[yRawData.size()];  
  214.         for (int i = 0; i < yRawData.size(); i++)  
  215.         {  
  216.             int ph = bheight - (int) (bheight * (yRawData.get(i) / maxValue));  
  217.   
  218.             points[i] = new Point(xList.get(i), ph + marginTop);  
  219.         }  
  220.         return points;  
  221.     }  
  222.   
  223.     public void setData(ArrayList<Double> yRawData, ArrayList<String> xRawData, int maxValue, int averageValue)  
  224.     {  
  225.         this.maxValue = maxValue;  
  226.         this.averageValue = averageValue;  
  227.         this.mPoints = new Point[yRawData.size()];  
  228.         this.xRawDatas = xRawData;  
  229.         this.yRawData = yRawData;  
  230.         this.spacingHeight = maxValue / averageValue;  
  231.     }  
  232.   
  233.     public void setTotalvalue(int maxValue)  
  234.     {  
  235.         this.maxValue = maxValue;  
  236.     }  
  237.   
  238.     public void setPjvalue(int averageValue)  
  239.     {  
  240.         this.averageValue = averageValue;  
  241.     }  
  242.   
  243.     public void setMargint(int marginTop)  
  244.     {  
  245.         this.marginTop = marginTop;  
  246.     }  
  247.   
  248.     public void setMarginb(int marginBottom)  
  249.     {  
  250.         this.marginBottom = marginBottom;  
  251.     }  
  252.   
  253.     public void setMstyle(Linestyle mStyle)  
  254.     {  
  255.         this.mStyle = mStyle;  
  256.     }  
  257.   
  258.     public void setBheight(int bheight)  
  259.     {  
  260.         this.bheight = bheight;  
  261.     }  
  262.   
  263.     /** 
  264.      * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 
  265.      */  
  266.     private int dip2px(float dpValue)  
  267.     {  
  268.         return (int) (dpValue * dm.density + 0.5f);  
  269.     }  
  270.   
  271. }  

      使用:

[java]  view plain copy
  1. package com.example;  
  2. import java.util.ArrayList;  
  3.   
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6.   
  7. public class MainActivity extends Activity  
  8. {  
  9.     LineGraphicView tu;  
  10.     ArrayList<Double> yList;  
  11.   
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState)  
  14.     {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.activity_main);  
  17.         tu = (LineGraphicView) findViewById(R.id.line_graphic);  
  18.   
  19.         yList = new ArrayList<Double>();  
  20.         yList.add((double2.103);  
  21.         yList.add(4.05);  
  22.         yList.add(6.60);  
  23.         yList.add(3.08);  
  24.         yList.add(4.32);  
  25.         yList.add(2.0);  
  26.         yList.add(5.0);  
  27.   
  28.         ArrayList<String> xRawDatas = new ArrayList<String>();  
  29.         xRawDatas.add("05-19");  
  30.         xRawDatas.add("05-20");  
  31.         xRawDatas.add("05-21");  
  32.         xRawDatas.add("05-22");  
  33.         xRawDatas.add("05-23");  
  34.         xRawDatas.add("05-24");  
  35.         xRawDatas.add("05-25");  
  36.         xRawDatas.add("05-26");  
  37.         tu.setData(yList, xRawDatas, 82);  
  38.     }  
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值