Android使用自定义View继承SurfaceView实现动态折线图的绘制

转载请标明出处:http://blog.csdn.net/klxh2009/article/details/50879618

请先看效果:


废话不多说,直接上代码:

一、layout:activity_main

[html]  view plain  copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"  
  6.     tools:context="com.shenhua.linechart.MainActivity"  
  7.     tools:ignore="PxUsage,RtlHardcoded" >  
  8.   
  9.     <RelativeLayout  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="60dp"  
  12.         android:background="#11CD6E" >  
  13.   
  14.         <Button  
  15.             android:id="@+id/button1"  
  16.             android:layout_width="35dp"  
  17.             android:layout_height="35dp"  
  18.             android:layout_alignParentLeft="true"  
  19.             android:layout_centerVertical="true"  
  20.             android:layout_marginLeft="10dp"  
  21.             android:background="@drawable/ic_menu" />  
  22.   
  23.         <TextView  
  24.             android:id="@+id/textView1"  
  25.             android:layout_width="wrap_content"  
  26.             android:layout_height="wrap_content"  
  27.             android:layout_centerVertical="true"  
  28.             android:layout_marginLeft="5dp"  
  29.             android:layout_toRightOf="@+id/button1"  
  30.             android:text="@string/app_name"  
  31.             android:textAppearance="?android:attr/textAppearanceLarge"  
  32.             android:textColor="@android:color/white" />  
  33.   
  34.         <Button  
  35.             android:id="@+id/button2"  
  36.             android:layout_width="32dp"  
  37.             android:layout_height="32dp"  
  38.             android:layout_alignParentRight="true"  
  39.             android:layout_centerVertical="true"  
  40.             android:layout_marginRight="10dp"  
  41.             android:background="@drawable/ic_setting" />  
  42.   
  43.         <Button  
  44.             android:id="@+id/button3"  
  45.             android:layout_width="32dp"  
  46.             android:layout_height="32dp"  
  47.             android:layout_centerVertical="true"  
  48.             android:layout_marginRight="10dp"  
  49.             android:layout_toLeftOf="@+id/button2"  
  50.             android:background="@drawable/ic_add" />  
  51.     </RelativeLayout>  
  52.   
  53.     <com.shenhua.linechart.MyLineChart  
  54.         android:id="@+id/linechart"  
  55.         android:layout_marginTop="20dp"  
  56.         android:layout_width="fill_parent"  
  57.         android:layout_height="280px" />  
  58.   
  59. </LinearLayout>  

二、attrs:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="MyLineChartView">  
  5.         <attr name="expend_color" format="color" />  
  6.         <attr name="income_color" format="color" />  
  7.         <attr name="table_color" format="color" />  
  8.         <attr name="tabletext_color" format="color" />  
  9.     </declare-styleable>  
  10.   
  11. </resources>  

三、MyLineChart:

[java]  view plain  copy
  1. package com.shenhua.linechart;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.graphics.Paint.Align;  
  9. import android.graphics.Paint.Style;  
  10. import android.graphics.PixelFormat;  
  11. import android.graphics.Rect;  
  12. import android.util.AttributeSet;  
  13. import android.view.SurfaceHolder;  
  14. import android.view.SurfaceView;  
  15.   
  16. public class MyLineChart extends SurfaceView implements SurfaceHolder.Callback {  
  17.   
  18.     private SurfaceHolder sfh;  
  19.     public static int right; // 坐标系右边距离框架左边的距离(由activity计算得出)  
  20.     public static int gapX; // 两根竖线间的间隙(由activity计算得出)  
  21.     private boolean isRunning = true;  
  22.     private static float[] Percent_Expend = { 6032.5f, 46007055100,  
  23.             5710.2f, 3010 };// 12个支出百分比  
  24.     private static float[] Percent_Income = { 00088025301057,  
  25.             88.2f, 300 };// 12个收入百分比  
  26.     private static String[] Percent = { "0""10""20""30""40""50",  
  27.             "60""70""80""90""100" };// 每个月支出的金额占全年总支出的百分比  
  28.     private String[] houres = { "1""2""3""4""5""6""7""8""9",  
  29.             "10""11""12 (月份)" };// 一年的12个月  
  30.     private int tick = 10// 时间间隔(ms)  
  31.     private int each_width = 20// 两根横线间的间隙  
  32.     private int top = 10// 坐标系顶部距离框架顶端框的距离  
  33.     private int bottom = top + each_width * 10;// 坐标系地段距离框架顶端的距离top+gapy*10=210  
  34.     private int left = 40// 坐标系左边距离框架左边框的距离  
  35.     private int currentX;  
  36.     private int oldX;  
  37.     private String title_expend = "• 每月支出金额占全年支出百分比";  
  38.     private String title_income = "• 每月收入金额占全年收入百分比";  
  39.     private int mExpendColor;  
  40.     private int mIncomeColor;  
  41.     private int mTableColor;  
  42.     private int mTableTextColor;  
  43.   
  44.     public MyLineChart(Context context) {  
  45.         super(context);  
  46.     }  
  47.   
  48.     public MyLineChart(Context context, AttributeSet atr) {  
  49.         super(context, atr);  
  50.         setZOrderOnTop(true);  
  51.         sfh = this.getHolder();  
  52.         sfh.addCallback(this);  
  53.         sfh.setFormat(PixelFormat.TRANSLUCENT);  
  54.         TypedArray typedArray = context.getTheme().obtainStyledAttributes(atr,  
  55.                 R.styleable.MyLineChartView, 00);  
  56.         mExpendColor = typedArray.getColor(  
  57.                 R.styleable.MyLineChartView_expend_color, Color.RED);  
  58.         mIncomeColor = typedArray  
  59.                 .getColor(R.styleable.MyLineChartView_income_color,  
  60.                         Color.rgb(018599));  
  61.         mTableColor = typedArray  
  62.                 .getColor(R.styleable.MyLineChartView_table_color,  
  63.                         Color.rgb(0214251));  
  64.         mTableTextColor = typedArray.getColor(  
  65.                 R.styleable.MyLineChartView_tabletext_color, Color.BLUE);  
  66.         typedArray.recycle();  
  67.     }  
  68.   
  69.     /** 
  70.      * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder) 
  71.      */  
  72.     @Override  
  73.     public void surfaceCreated(SurfaceHolder holder) {  
  74.         isRunning = true;  
  75.         currentX = 0;  
  76.         Thread thread = new Thread(new Runnable() {  
  77.             @Override  
  78.             public void run() {  
  79.                 gridDraw();  
  80.                 drawChartLine();  
  81.             }  
  82.         });  
  83.         thread.start();  
  84.     }  
  85.   
  86.     @Override  
  87.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  
  88.     }  
  89.   
  90.     @Override  
  91.     public void surfaceDestroyed(SurfaceHolder arg0) {  
  92.         isRunning = false;  
  93.     }  
  94.   
  95.     protected void gridDraw() {  
  96.         Canvas canvas = sfh.lockCanvas();  
  97.         Paint mTablePaint = new Paint();  
  98.         mTablePaint.setColor(mTableColor);  
  99.         mTablePaint.setAntiAlias(true);  
  100.         mTablePaint.setStrokeWidth(1);  
  101.         mTablePaint.setStyle(Style.FILL);  
  102.         Paint mTableTextPaint = new Paint();  
  103.         mTableTextPaint.setAntiAlias(true);  
  104.         mTableTextPaint.setColor(mTableTextColor);  
  105.         mTableTextPaint.setTextSize(12f);  
  106.         Paint mExpendPaint = new Paint();  
  107.         mExpendPaint.setColor(mExpendColor);  
  108.         mExpendPaint.setTextSize(16f);  
  109.         Paint mIncomePaint = new Paint();  
  110.         mIncomePaint.setColor(mIncomeColor);  
  111.         mIncomePaint.setTextSize(16f);  
  112.         // 绘制坐标系  
  113.         for (int i = 0; i < 11; i++) {  
  114.             canvas.drawLine(left, top + each_width * i, left + gapX * 11, top  
  115.                     + each_width * i, mTablePaint);  
  116.             mTableTextPaint.setTextAlign(Align.RIGHT);  
  117.             canvas.drawText("" + Percent[i], left - 2, bottom + 3 - 20 * i,  
  118.                     mTableTextPaint);  
  119.         }  
  120.         for (int i = 0; i < 12; i++) {  
  121.             canvas.drawLine(left + gapX * i, top, left + gapX * i, bottom,  
  122.                     mTablePaint);  
  123.             mTableTextPaint.setTextAlign(Align.CENTER);  
  124.             canvas.drawText(houres[i], left + gapX * i, bottom + 14,  
  125.                     mTableTextPaint);  
  126.         }  
  127.         Rect mBound_expend = new Rect();  
  128.         mExpendPaint.getTextBounds(title_expend, 0, title_expend.length(),  
  129.                 mBound_expend);  
  130.         canvas.drawText(title_expend, getWidth() / 2 - mBound_expend.width()  
  131.                 / 2, bottom + 40, mExpendPaint);  
  132.   
  133.         Rect mBound_income = new Rect();  
  134.         mIncomePaint.getTextBounds(title_income, 0, title_income.length(),  
  135.                 mBound_income);  
  136.         canvas.drawText(title_income, getWidth() / 2 - mBound_income.width()  
  137.                 / 2, bottom + 60, mIncomePaint);  
  138.   
  139.         sfh.unlockCanvasAndPost(canvas);  
  140.     }  
  141.   
  142.     private void drawChartLine() {  
  143.         while (isRunning) {  
  144.             try {  
  145.                 drawChart(currentX);  
  146.                 currentX++;  
  147.                 try {  
  148.                     Thread.sleep(tick);  
  149.                 } catch (InterruptedException e) {  
  150.                     e.printStackTrace();  
  151.                 }  
  152.             } catch (Exception e) {  
  153.                 System.out.println("绘制出错!");  
  154.             }  
  155.         }  
  156.     }  
  157.   
  158.     void drawChart(int length) {  
  159.         if (length == 0)  
  160.             oldX = 0;  
  161.         Canvas canvas = sfh.lockCanvas(new Rect(oldX, 0, oldX + length,  
  162.                 bottom + 30));  
  163.         drawExpend(canvas);  
  164.         drawIncome(canvas);  
  165.         sfh.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像  
  166.     }  
  167.   
  168.     private void drawIncome(Canvas canvas) {  
  169.         Paint mPointPaint = new Paint();  
  170.         mPointPaint.setAntiAlias(true);  
  171.         mPointPaint.setColor(mIncomeColor);  
  172.         Paint mLinePaint = new Paint();  
  173.         mLinePaint.setColor(mIncomeColor);  
  174.         mLinePaint.setAntiAlias(true);  
  175.         mLinePaint.setStrokeWidth(2);  
  176.         mLinePaint.setStyle(Style.FILL);  
  177.         float cx = 0f;  
  178.         float cy = 0f;  
  179.         float dx = 0f;  
  180.         float dy = 0f;  
  181.         for (int j = 0; j < Percent_Income.length - 1; j++) {  
  182.             cx = left + gapX * j;  
  183.             cy = bottom - (Percent_Income[j] * 0.1f) * each_width;  
  184.             dx = left + gapX * (j + 1);  
  185.             dy = bottom - (Percent_Income[j + 1] * 0.1f) * each_width;  
  186.             canvas.drawCircle(cx, cy, 3, mPointPaint);  
  187.             canvas.drawLine(cx, cy, dx, dy, mLinePaint);  
  188.         }  
  189.     }  
  190.   
  191.     private void drawExpend(Canvas canvas) {  
  192.         Paint mPointPaint = new Paint();  
  193.         mPointPaint.setAntiAlias(true);  
  194.         mPointPaint.setColor(mExpendColor);  
  195.         Paint mLinePaint = new Paint();  
  196.         mLinePaint.setColor(mExpendColor);  
  197.         mLinePaint.setAntiAlias(true);  
  198.         mLinePaint.setStrokeWidth(2);  
  199.         mLinePaint.setStyle(Style.FILL);  
  200.         float cx = 0f;  
  201.         float cy = 0f;  
  202.         float dx = 0f;  
  203.         float dy = 0f;  
  204.         for (int j = 0; j < Percent_Expend.length - 1; j++) {  
  205.             cx = left + gapX * j;  
  206.             cy = bottom - (Percent_Expend[j] * 0.1f) * each_width;  
  207.             dx = left + gapX * (j + 1);  
  208.             dy = bottom - (Percent_Expend[j + 1] * 0.1f) * each_width;  
  209.             canvas.drawCircle(cx, cy, 3, mPointPaint);  
  210.             canvas.drawLine(cx, cy, dx, dy, mLinePaint);  
  211.         }  
  212.     }  
  213.   
  214. }  

四、MainActivity:

[java]  view plain  copy
  1. package com.shenhua.linechart;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.util.DisplayMetrics;  
  6. import android.util.Log;  
  7. import android.view.Window;  
  8.   
  9. public class MainActivity extends Activity {  
  10.   
  11.     @Override  
  12.     protected void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  15.         setContentView(R.layout.activity_main);  
  16.   
  17.         DisplayMetrics dm = new DisplayMetrics();  
  18.         getWindowManager().getDefaultDisplay().getMetrics(dm);  
  19.         int width = dm.widthPixels;  
  20.         int height = dm.heightPixels;  
  21.         Log.d("系统信息""该设备的分辨是:" + width + "*" + height);  
  22.         MyLineChart.right = width - 35;  
  23.         MyLineChart.gapX = (width - 70) / 11;  
  24.     }  
  25.   
  26. }  

附上 GitHub Demo:https://github.com/shenhuanet/LineChart
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值