转载请标明出处:http://blog.csdn.net/klxh2009/article/details/50879618
请先看效果:
废话不多说,直接上代码:
一、layout:activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.shenhua.linechart.MainActivity" tools:ignore="PxUsage,RtlHardcoded" > <RelativeLayout android:layout_width="match_parent" android:layout_height="60dp" android:background="#11CD6E" > <Button android:id="@+id/button1" android:layout_width="35dp" android:layout_height="35dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:background="@drawable/ic_menu" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:layout_toRightOf="@+id/button1" android:text="@string/app_name" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@android:color/white" /> <Button android:id="@+id/button2" android:layout_width="32dp" android:layout_height="32dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:background="@drawable/ic_setting" /> <Button android:id="@+id/button3" android:layout_width="32dp" android:layout_height="32dp" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:layout_toLeftOf="@+id/button2" android:background="@drawable/ic_add" /> </RelativeLayout> <com.shenhua.linechart.MyLineChart android:id="@+id/linechart" android:layout_marginTop="20dp" android:layout_width="fill_parent" android:layout_height="280px" /> </LinearLayout>
二、attrs:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyLineChartView"> <attr name="expend_color" format="color" /> <attr name="income_color" format="color" /> <attr name="table_color" format="color" /> <attr name="tabletext_color" format="color" /> </declare-styleable> </resources>
三、MyLineChart:
package com.shenhua.linechart; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.PixelFormat; import android.graphics.Rect; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MyLineChart extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder sfh; public static int right; // 坐标系右边距离框架左边的距离(由activity计算得出) public static int gapX; // 两根竖线间的间隙(由activity计算得出) private boolean isRunning = true; private static float[] Percent_Expend = { 60, 32.5f, 46, 0, 0, 70, 55, 100, 57, 10.2f, 30, 10 };// 12个支出百分比 private static float[] Percent_Income = { 0, 0, 0, 88, 0, 25, 30, 10, 57, 88.2f, 30, 0 };// 12个收入百分比 private static String[] Percent = { "0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100" };// 每个月支出的金额占全年总支出的百分比 private String[] houres = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12 (月份)" };// 一年的12个月 private int tick = 10; // 时间间隔(ms) private int each_width = 20; // 两根横线间的间隙 private int top = 10; // 坐标系顶部距离框架顶端框的距离 private int bottom = top + each_width * 10;// 坐标系地段距离框架顶端的距离top+gapy*10=210 private int left = 40; // 坐标系左边距离框架左边框的距离 private int currentX; private int oldX; private String title_expend = "• 每月支出金额占全年支出百分比"; private String title_income = "• 每月收入金额占全年收入百分比"; private int mExpendColor; private int mIncomeColor; private int mTableColor; private int mTableTextColor; public MyLineChart(Context context) { super(context); } public MyLineChart(Context context, AttributeSet atr) { super(context, atr); setZOrderOnTop(true); sfh = this.getHolder(); sfh.addCallback(this); sfh.setFormat(PixelFormat.TRANSLUCENT); TypedArray typedArray = context.getTheme().obtainStyledAttributes(atr, R.styleable.MyLineChartView, 0, 0); mExpendColor = typedArray.getColor( R.styleable.MyLineChartView_expend_color, Color.RED); mIncomeColor = typedArray .getColor(R.styleable.MyLineChartView_income_color, Color.rgb(0, 185, 99)); mTableColor = typedArray .getColor(R.styleable.MyLineChartView_table_color, Color.rgb(0, 214, 251)); mTableTextColor = typedArray.getColor( R.styleable.MyLineChartView_tabletext_color, Color.BLUE); typedArray.recycle(); } /** * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder) */ @Override public void surfaceCreated(SurfaceHolder holder) { isRunning = true; currentX = 0; Thread thread = new Thread(new Runnable() { @Override public void run() { gridDraw(); drawChartLine(); } }); thread.start(); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } @Override public void surfaceDestroyed(SurfaceHolder arg0) { isRunning = false; } protected void gridDraw() { Canvas canvas = sfh.lockCanvas(); Paint mTablePaint = new Paint(); mTablePaint.setColor(mTableColor); mTablePaint.setAntiAlias(true); mTablePaint.setStrokeWidth(1); mTablePaint.setStyle(Style.FILL); Paint mTableTextPaint = new Paint(); mTableTextPaint.setAntiAlias(true); mTableTextPaint.setColor(mTableTextColor); mTableTextPaint.setTextSize(12f); Paint mExpendPaint = new Paint(); mExpendPaint.setColor(mExpendColor); mExpendPaint.setTextSize(16f); Paint mIncomePaint = new Paint(); mIncomePaint.setColor(mIncomeColor); mIncomePaint.setTextSize(16f); // 绘制坐标系 for (int i = 0; i < 11; i++) { canvas.drawLine(left, top + each_width * i, left + gapX * 11, top + each_width * i, mTablePaint); mTableTextPaint.setTextAlign(Align.RIGHT); canvas.drawText("" + Percent[i], left - 2, bottom + 3 - 20 * i, mTableTextPaint); } for (int i = 0; i < 12; i++) { canvas.drawLine(left + gapX * i, top, left + gapX * i, bottom, mTablePaint); mTableTextPaint.setTextAlign(Align.CENTER); canvas.drawText(houres[i], left + gapX * i, bottom + 14, mTableTextPaint); } Rect mBound_expend = new Rect(); mExpendPaint.getTextBounds(title_expend, 0, title_expend.length(), mBound_expend); canvas.drawText(title_expend, getWidth() / 2 - mBound_expend.width() / 2, bottom + 40, mExpendPaint); Rect mBound_income = new Rect(); mIncomePaint.getTextBounds(title_income, 0, title_income.length(), mBound_income); canvas.drawText(title_income, getWidth() / 2 - mBound_income.width() / 2, bottom + 60, mIncomePaint); sfh.unlockCanvasAndPost(canvas); } private void drawChartLine() { while (isRunning) { try { drawChart(currentX); currentX++; try { Thread.sleep(tick); } catch (InterruptedException e) { e.printStackTrace(); } } catch (Exception e) { System.out.println("绘制出错!"); } } } void drawChart(int length) { if (length == 0) oldX = 0; Canvas canvas = sfh.lockCanvas(new Rect(oldX, 0, oldX + length, bottom + 30)); drawExpend(canvas); drawIncome(canvas); sfh.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像 } private void drawIncome(Canvas canvas) { Paint mPointPaint = new Paint(); mPointPaint.setAntiAlias(true); mPointPaint.setColor(mIncomeColor); Paint mLinePaint = new Paint(); mLinePaint.setColor(mIncomeColor); mLinePaint.setAntiAlias(true); mLinePaint.setStrokeWidth(2); mLinePaint.setStyle(Style.FILL); float cx = 0f; float cy = 0f; float dx = 0f; float dy = 0f; for (int j = 0; j < Percent_Income.length - 1; j++) { cx = left + gapX * j; cy = bottom - (Percent_Income[j] * 0.1f) * each_width; dx = left + gapX * (j + 1); dy = bottom - (Percent_Income[j + 1] * 0.1f) * each_width; canvas.drawCircle(cx, cy, 3, mPointPaint); canvas.drawLine(cx, cy, dx, dy, mLinePaint); } } private void drawExpend(Canvas canvas) { Paint mPointPaint = new Paint(); mPointPaint.setAntiAlias(true); mPointPaint.setColor(mExpendColor); Paint mLinePaint = new Paint(); mLinePaint.setColor(mExpendColor); mLinePaint.setAntiAlias(true); mLinePaint.setStrokeWidth(2); mLinePaint.setStyle(Style.FILL); float cx = 0f; float cy = 0f; float dx = 0f; float dy = 0f; for (int j = 0; j < Percent_Expend.length - 1; j++) { cx = left + gapX * j; cy = bottom - (Percent_Expend[j] * 0.1f) * each_width; dx = left + gapX * (j + 1); dy = bottom - (Percent_Expend[j + 1] * 0.1f) * each_width; canvas.drawCircle(cx, cy, 3, mPointPaint); canvas.drawLine(cx, cy, dx, dy, mLinePaint); } } }
四、MainActivity:
package com.shenhua.linechart; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.Window; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int width = dm.widthPixels; int height = dm.heightPixels; Log.d("系统信息", "该设备的分辨是:" + width + "*" + height); MyLineChart.right = width - 35; MyLineChart.gapX = (width - 70) / 11; } }