1. 程式人生 > >android自定義統計折線圖和柱狀圖組合

android自定義統計折線圖和柱狀圖組合

本程式碼是一年前公司專案需要自己所寫,當時做android專案需要統計的功能,統計的圖表包括餅圖、柱狀圖、折線圖,程式碼寫的有些笨拙!希望大家能夠看懂!其程式碼做拋磚引玉,希望大家能夠再改寫下!可以用多執行緒做出動畫,是不是更好呢?這些後期我也沒有整理過,所以誰能再整理下!此含有柱狀圖和折線圖的組合,有興趣的可以拆分成單個的折線圖和柱狀圖。

LineHistogram.java

package com.wforyou.dhh.ui.widget;

import java.util.Arrays;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.View.MeasureSpec;

public class LineHistogram extends View {

	
	private int mAscent;
	
	private String mText="";
	// 螢幕的高度
	public static int heightPixels = 0;

	// 螢幕的寬度
	public static int widthPixels = 0;

	// X軸
	public static float XLength = 600.f;

	// Y軸
	public static float Ylength = 300.0f;

	// X軸最大值
	public static float XMAXLENGTH = 2500.0f;

	// Y軸最大值
	public static float YMAXLENGTH = 250.0f;

	// 畫筆
	private static Paint paint;

	// 距離螢幕左邊的距離
	private static float marginleft = 0;

	// 距離螢幕上邊的距離
	private static float margintop = 0;

	// 統計圖的標題
	public String NoteText = "";

	// 實際提示資訊
	public String thinkNoteText = ""; 

	// 計劃提示資訊
	public String realityNoteText = "";

	// 平均刻度值
	public static int average = 40;

	// y軸刻度的平均值,需要幾個刻度
	public static int yaverage = 6;

	// 以多少畫素取幾個刻度
	public static float faverage = 50;

	// x軸刻度的間距
	public static float xaverage = 40;

	/**文字資訊**/
	public String[] ValuesText = { "褲子", "文胸", "T恤", "襯衣", "保暖衣", "保暖褲",
			"頭巾", "圍巾" };

	/**計劃所對應的金額**/
	public double[] thinkValues = { 360, 400, 600, 2000, 1500, 485, 315,
			365 };

	/**實際所對應的金額**/
	public double[] realityValues = { 300, 180, 150, 180, 900, 35, 255, 125 };

	/**計劃金額的顏色**/
	public static int thinkcolor = Color.parseColor("#004882");

	/**實際金額的顏色**/
	public static int truecolor = Color.parseColor("#C96118");

	/**平均刻度值與實際刻度值的比**/
	public static float xpaverage = 1;

	/**Y軸提示資訊**/
	public static String yText="金額";
	
	/**x軸提示資訊**/
	public static String xText="";
	/**文字資訊的間距**/
	public static float yspace=60;
	
	
	public LineHistogram(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public LineHistogram(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public LineHistogram(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onDraw(Canvas canvas) {

		getWidthHeigth();
		getmaxyLength();
		Log.v("msg", "hello world data " + String.valueOf(XMAXLENGTH));

		Log.v("msg", "heightPixels = " + String.valueOf(heightPixels)
				+ "  widthPixels = " + String.valueOf(widthPixels)
				+ "  XLength = " + String.valueOf(XLength) + "  Ylength = "
				+ String.valueOf(Ylength));
		canvas.drawColor(Color.WHITE);

		paint = new Paint();
		paint.setAntiAlias(true);  
		
		DrawXY(canvas);

		drawCentreNote(canvas);

		drawNoteText(canvas);

		getyaverage();

		getAverage(XMAXLENGTH);

		getxpaverage();

		DrawYText(canvas);

		DrawValuesText(canvas);

		drawtrue(canvas);

		drawthink(canvas);
	}

	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(measureWidth(widthMeasureSpec),
				measureHeight(heightMeasureSpec));
	}
	
	private void getWidthHeigth() {
//		DisplayMetrics metrics = getResources().getDisplayMetrics();
//
//		// 螢幕高
//		heightPixels = metrics.heightPixels;
//		// 螢幕寬
//		widthPixels = metrics.widthPixels;
		
		// 螢幕高
		heightPixels =getHeight();
				// 螢幕寬
		widthPixels = getWidth();

		marginleft=getPaddingLeft()+50f;
		margintop=getPaddingTop()+60f;

		// X軸
		XLength = widthPixels;
		// Y軸
		Ylength = heightPixels -70;
	}

	public void DrawXY(Canvas canvas) {
		
		paint.setColor(Color.BLACK);

//		canvas.drawLine(marginleft, margintop, marginleft + 5, margintop + 5,
//				paint);// 畫右下箭頭
//		canvas.drawLine(marginleft, margintop, marginleft - 5, margintop + 4,
//				paint);// 畫左上箭頭

		canvas.drawLine(marginleft, margintop, marginleft, Ylength, paint);
		canvas.drawLine(marginleft, Ylength, XLength, Ylength, paint);

//		canvas.drawLine(XLength - 5.0f, Ylength + 5.0f, XLength, Ylength, paint);// 畫箭頭
//		canvas.drawLine(XLength - 5.0f, Ylength - 5.0f, XLength, Ylength, paint);// 畫箭頭
	}

	public void drawNoteText(Canvas canvas) {
		paint.setColor(Color.BLACK);
		paint.setTextSize(20);

		canvas.drawText(NoteText,
				((float) ((XLength - paint.measureText(NoteText)) / 2)), margintop+20,
				paint);
	}

	public void drawNote(Canvas canvas) {
		paint.setColor(truecolor);
		paint.setTextSize(15);
		canvas.drawRect(marginleft, Ylength + 45f, marginleft + 10f,
				Ylength + 55f, paint);
		canvas.drawText(thinkNoteText, marginleft + 20f, Ylength + 55f, paint);

		paint.setColor(thinkcolor);
		canvas.drawLine(marginleft + 30f + paint.measureText(thinkNoteText),
				Ylength + 40f, marginleft + 43f + paint.measureText(thinkNoteText),
				Ylength + 50f, paint);
		canvas.drawText(realityNoteText,
				marginleft + 50f + paint.measureText(thinkNoteText), Ylength + 55f,
				paint);

		canvas.drawLine(0, 492, XLength, 492, paint);
	}
	
	/**
	 * 提示資訊畫中心
	 * @param canvas
	 */
	public void drawCentreNote(Canvas canvas) {
		float temp=XLength/2;//得到螢幕中間的畫素值
		paint.setColor(thinkcolor);//設定顏色
		paint.setTextSize(15);//設定字型
		
		//畫圓左邊線
		canvas.drawLine(temp-paint.measureText(thinkNoteText)-50f, Ylength+50, temp-paint.measureText(thinkNoteText)-40f, Ylength+50, paint);
		//畫大圓
		canvas.drawCircle(temp-paint.measureText(thinkNoteText)-35f, Ylength+50, 5, paint);
		//設定顏色
		paint.setColor(Color.WHITE);
		//畫小圓切割大圓成環形
		canvas.drawCircle(temp-paint.measureText(thinkNoteText)-35f, Ylength+50, 2.5f, paint);
		
		paint.setColor(thinkcolor);
		//畫圓右邊的線
		canvas.drawLine(temp-paint.measureText(thinkNoteText)-30f, Ylength+50, temp-paint.measureText(thinkNoteText)-20f, Ylength+50, paint);

		paint.setColor(Color.BLACK);
		//畫提示資訊
		canvas.drawText(thinkNoteText, temp-paint.measureText(thinkNoteText)-10, Ylength+55, paint);
		
		
		paint.setColor(truecolor);
		
		//畫矩形
		canvas.drawRect(temp+10, Ylength+45, temp+20, Ylength+55, paint);
		
		paint.setColor(Color.BLACK);
		//畫提示資訊
		canvas.drawText(realityNoteText, temp+30, Ylength+55, paint);
		
		canvas.drawText("0", marginleft-10f, Ylength+10, paint);
	
	}


	public String getAverage(double d) {
		String strRtn = "0";
		int intnum = (int) (d / yaverage);

		int inttemp = Integer
				.valueOf(getNumber(String.valueOf(intnum).length()));
		if (inttemp == 1) {
			strRtn = String
					.valueOf((int) (d % yaverage) == 0 ? ((int) (d / yaverage))
							: ((int) (d / yaverage) + 1));
		} else {
			strRtn = String.valueOf(intnum % inttemp == 0 ? (intnum / inttemp)
					* inttemp : (intnum / inttemp + 1) * inttemp);
		}
		average = Integer.valueOf(strRtn);
		Log.v("msg", "average = " + String.valueOf(average) + " YMAXLENGTH = "
				+ String.valueOf(YMAXLENGTH));
		return strRtn;
	}

	public void getyaverage() {
		yaverage = (int) ((Ylength - margintop - 10) % faverage == 0.0 ? (Ylength
				- margintop - 10)
				/ faverage
				: (Ylength - margintop - 10) / faverage);
		Log.v("msg", "Ylength = " + String.valueOf(Ylength) + " yaverage = "
				+ String.valueOf(yaverage));
		Log.v("msg",
				"data  =  "
						+ String.valueOf((Ylength - margintop - 10) % faverage)
						+ "  length = "
						+ String.valueOf(Ylength - margintop - 10));
		Log.v("msg",
				"rtn1 = "
						+ String.valueOf((Ylength - margintop - 10) / faverage)
						+ "  Rtn2 = "
						+ String.valueOf((Ylength - margintop - 10) / faverage));
	}

	public void getxpaverage() {
		xpaverage = average / faverage;
		Log.v("msg", "xp =" + String.valueOf(xpaverage));
	}

	public String getNumber(int num) {
		String strRtn = "1";
		if (num > 0) {
			for (int i = 0; i < num - 1; i++) {
				strRtn += "0";
			}
		}
		return strRtn;
	}

	public void DrawYText(Canvas canvas) {
		paint.setColor(Color.BLACK);
		Float temp = 0.0f;
		paint.setTextSize(12);
		for (int i = 1; i < yaverage + 1; i++) {
			paint.setColor(Color.BLACK);
			temp = Ylength - Float.valueOf(faverage * i);
			Log.v("msg", String.valueOf(temp));
//			canvas.drawLine(marginleft - 10, temp, marginleft, temp, paint);
			canvas.drawText(String.valueOf(Integer.valueOf(average) * i), marginleft-paint.measureText(String.valueOf(Integer.valueOf(average) * i))-5,
					temp + 4.5f, paint);
			paint.setColor(Color.parseColor("#9EADD1"));
			canvas.drawLine(marginleft, temp, XLength, temp, paint);
		}
		paint.setColor(Color.BLACK);
		canvas.drawLine(marginleft, margintop, marginleft, margintop+10, paint);
		paint.setTextSize(15);
        canvas.drawText(yText,marginleft-paint.measureText(yText)-5f,Ylength-15, paint);
		
		canvas.drawText(xText,marginleft,Ylength+40, paint);
	}

	public void DrawValuesText(Canvas canvas) {
		paint.setColor(Color.BLACK);
		float temp = marginleft-20f;
		for (int i = 0; i < ValuesText.length; i++) {
			temp += yspace;
			canvas.drawLine(temp, Ylength, temp, Ylength + 5f, paint);
			canvas.drawText(ValuesText[i], temp - (paint.measureText(ValuesText[i])/2), Ylength + 20f, paint);
		}
	}

	public void getmaxyLength() {
		double temp = thinkValues[0];
		for (int i = 1; i < thinkValues.length; i++) {
			if (temp < thinkValues[i]) {
				temp = thinkValues[i];
			}
		}
		for (int i = 0; i <realityValues.length; i++) {
			if (temp < realityValues[i]) {
				temp = realityValues[i];
			}
		}
		XMAXLENGTH = (float) temp;
	}

	public void DrawXthinkText(Canvas canvas) {

		float temp = marginleft-20;
		for (int i = 0; i < thinkValues.length; i++) {
			temp += yspace;
			paint.setColor(thinkcolor);
			canvas.drawRect(temp - 20.0f, Ylength - (float) (thinkValues[i]),
					temp, Ylength, paint);
			canvas.drawText(String.valueOf((int) thinkValues[i]), temp - 20.0f,
					(float) (Ylength - thinkValues[i] - 3.0f), paint);
			paint.setColor(truecolor);
			canvas.drawRect(temp, Ylength - (float) (realityValues[i]), temp + 20.f,
					Ylength, paint);
			canvas.drawText(String.valueOf((int) realityValues[i]), temp,
					(float) (Ylength - realityValues[i] - 3.0f), paint);
			Log.v("msg",
					"data" + String.valueOf(Ylength - (float) (thinkValues[i])));
		}
	}

	public void drawthink(Canvas canvas) {
		paint.setColor(thinkcolor);
		float temp = marginleft-20;
		for (int i = 0; i < thinkValues.length - 1; i++) {
			temp += yspace;
			canvas.drawLine(temp, Ylength
					- (float) (thinkValues[i] / xpaverage), temp += yspace,
					Ylength - (float) (thinkValues[i + 1] / xpaverage), paint);
			temp -= yspace;
		}

		temp = marginleft-20;
		for (int i = 0; i < thinkValues.length; i++) {
			temp += yspace;
			paint.setColor(thinkcolor);
			canvas.drawText(String.valueOf(thinkValues[i]), temp - (paint.measureText(String.valueOf(thinkValues[i]))/2),
					Ylength - (float) (thinkValues[i] / xpaverage) - 7.0f,
					paint);
			canvas.drawCircle(temp, Ylength
					- (float) (thinkValues[i] / xpaverage), 5.0f, paint);
			paint.setColor(Color.WHITE);
			canvas.drawCircle(temp, Ylength
					- (float) (thinkValues[i] / xpaverage), 2.5f, paint);
		}
	}

	public void drawtrue(Canvas canvas) {
		float temp = marginleft-20;
		paint.setColor(truecolor);
		
		for (int i = 0; i < realityValues.length; i++) {
			temp += yspace;
			canvas.drawRect(temp - 15.0f, Ylength
					- (float) (realityValues[i] / xpaverage), temp + 15.0f, Ylength,
					paint);
		}
		
		paint.setColor(Color.BLACK);
		temp = marginleft-20;
		for (int i = 0; i < realityValues.length; i++) {
			temp += yspace;
			canvas.drawText(String.valueOf(realityValues[i]), temp - (paint.measureText(String.valueOf(realityValues[i]))/2),
					Ylength - 20.0f, paint);
		}
	}
	
	private int measureWidth(int measureSpec) {
		paint=new Paint();
		int result = 0;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);

		if (specMode == MeasureSpec.EXACTLY) {
			// We were told how big to be
			result = specSize;
		} else {
			// Measure the text
			if(mText.equals("")){
				DisplayMetrics metrics = getResources().getDisplayMetrics();
				result = (int) (metrics.widthPixels<getAcquiesceWhidth()?getAcquiesceWhidth():metrics.widthPixels+getPaddingLeft()
						+ getPaddingRight());
			}else{
				result = (int) paint.measureText(mText) + getPaddingLeft()
						+ getPaddingRight();
			}
			
			if (specMode == MeasureSpec.AT_MOST) {
				// Respect AT_MOST value if that was what is called for by
				// measureSpec
				result = Math.min(result, specSize);
			}
		}

		return result;
	}

	/**
	 * Determines the height of this view
	 * 
	 * @param measureSpec
	 *            A measureSpec packed into an int
	 * @return The height of the view, honoring constraints from measureSpec
	 */
	private int measureHeight(int measureSpec) {
		paint = new Paint();
		int result = 0;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);

		mAscent = (int) paint.ascent();
		if (specMode == MeasureSpec.EXACTLY) {
			// We were told how big to be
			result = specSize;
		} else {
			if (mText.equals("")) {
				DisplayMetrics metrics = getResources().getDisplayMetrics();
				result = (int) (metrics.heightPixels-150 + getPaddingLeft() + getPaddingRight());
			} else {
				result = (int) (-mAscent + paint.descent()) + getPaddingTop()
						+ getPaddingBottom();
			}
			if (specMode == MeasureSpec.AT_MOST) {
				result = Math.min(result, specSize);
			}
		}
		return result;
	}
	
	public float getAcquiesceWhidth(){
		float rtn=100;
		if(ValuesText.length>0){
			rtn=getPaddingLeft()+40+(yspace*(ValuesText.length+1));
		}
		return rtn;
	}

	public String getNoteText() {
		return NoteText;
	}

	public void setNoteText(String noteText) {
		NoteText = noteText;
	}

	public String getThinkNoteText() {
		return thinkNoteText;
	}

	public void setThinkNoteText(String thinkNoteText) {
		this.thinkNoteText = thinkNoteText;
	}

	public String getRealityNoteText() {
		return realityNoteText;
	}

	public void setRealityNoteText(String realityNoteText) {
		this.realityNoteText = realityNoteText;
	}

	public String[] getValuesText() {
		return ValuesText;
	}

	public void setValuesText(String[] valuesText) {
		ValuesText = valuesText;
	}

	public double[] getThinkValues() {
		return thinkValues;
	}

	public void setThinkValues(double[] thinkValues) {
		this.thinkValues = thinkValues;
	}

	public double[] getRealityValues() {
		return realityValues;
	}

	public void setRealityValues(double[] realityValues) {
		this.realityValues = realityValues;
	}

	@Override
	public String toString() {
		return "LineHistogram [mAscent=" + mAscent + ", mText=" + mText
				+ ", NoteText=" + NoteText + ", thinkNoteText=" + thinkNoteText
				+ ", realityNoteText=" + realityNoteText + ", ValuesText="
				+ Arrays.toString(ValuesText) + ", thinkValues="
				+ Arrays.toString(thinkValues) + ", realityValues="
				+ Arrays.toString(realityValues) + "]";
	}
	
}


用法

/**大類數量比例**/
	private Cookie mCkAddTypeQuantity;
	
	/**預期和實際對比**/
	private LineHistogram mHgAddContrast;
public void getDataContrast(String muserID) {
		SqlStatistics service = new SqlStatistics(getActivity());
		DHHApp.setUserId("J0049");
		ArrayList<OrderStatistics> arrayList = service.getSumAmount(true);
		Logs.v("msg", "test data = " + arrayList.toString());
		String[] thinkdata = new String[arrayList.size()];
		double[] thinkNumber = new double[arrayList.size()];
		double[] trueNumber = new double[arrayList.size()];
		int intcount = 0;
		for (OrderStatistics orderStatistics : arrayList) {
			thinkdata[intcount] = orderStatistics.getShowName();
			thinkNumber[intcount] = orderStatistics.getShowSecondNumber();
			trueNumber[intcount]=orderStatistics.getShowNumber();
			intcount++;
		}
		mHgAddContrast.setValuesText(thinkdata);
		mHgAddContrast.setThinkValues(thinkNumber);
		mHgAddContrast.setRealityValues(trueNumber);
		mHgAddContrast.setRealityNoteText("實際訂購金額");
		mHgAddContrast.setThinkNoteText("計劃訂購金額");
		mHgAddContrast.setNoteText("");
	}


佈局

 <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical" >

                <com.wforyou.dhh.ui.widget.LineHistogram
                    android:id="@+id/user_LineHistogram_Contrast"
                    android:layout_width="match_parent"
                    android:layout_height="fill_parent" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="35dp"
                    android:layout_marginTop="20dp"
                    android:background="@drawable/bg_tb_left"
                    android:paddingLeft="60dp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="20dp"
                    android:background="@drawable/bg_user_plancontrast" />
            </RelativeLayout>