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

来源:互联网 发布:sql over partition by 编辑:程序博客网 时间:2024/06/05 04:09

转载请标明出处: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=210private 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) */@Overridepublic void surfaceCreated(SurfaceHolder holder) {isRunning = true;currentX = 0;Thread thread = new Thread(new Runnable() {@Overridepublic void run() {gridDraw();drawChartLine();}});thread.start();}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}@Overridepublic 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 {@Overrideprotected 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;}}

附上 GitHub Demo:https://github.com/shenhuanet/LineChart

0 0