1. 程式人生 > >android 自定義餅圖

android 自定義餅圖

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

CookieData.java

class CookieData

package com.wforyou.dhh.ui.widget;

public class CookieData {

	/**名稱**/
	private String name;
	
	/**數值**/
	private double data;
	
	/**顏色**/
	private int color;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getData() {
		return data;
	}

	public void setData(double data) {
		this.data = data;
	}

	public int getColor() {
		return color;
	}

	public void setColor(int color) {
		this.color = color;
	}

	@Override
	public String toString() {
		return "CookieData [name=" + name + ", data=" + data + ", color="
				+ color + "]";
	}
}

Cookie.java

package com.wforyou.dhh.ui.widget;

import com.wforyou.dhh.util.Logs;

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

public class Cookie extends View {

	private int mAscent;

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

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

	/** 畫筆 **/
	private static Paint paint;

	/** 半徑 **/
	private float radius = 130;

	/** X起點座標 **/
	private static float xstartcoordinate = 100;

	/** Y起點座標 **/
	private static float ystartcoordinate = 180;

	/** X終點座標 **/
	private static float xendcoordinate = 400;

	/** Y終點座標 **/
	private static float yendcoordinate = 180;

	private static RectF f;

	private static int[] colors = { Color.parseColor("#29A3A4"),
			Color.parseColor("#4239A2"), Color.parseColor("#9C46FF"),
			Color.parseColor("#E8C000"), Color.parseColor("#4B0064"),
			Color.parseColor("#16699B"), Color.parseColor("#3E635B"),
			Color.parseColor("#B19862"), Color.parseColor("#F736F7"),
			Color.parseColor("#164988") };

	private String[] textValues = { "褲子", "裙子", "內褲", "文胸", "保暖衣" };

	private double[] numberValues = { 63, 80, 0, 150, 140 };

	private String noteText = "";

	private static float statar = 0;

	private static float addx = 0;

	private static float addy = 0;

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

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

	// 距離螢幕右邊的距離
	private static float marginrigth = 0;

	// 距離螢幕下邊的距離
	private static float margindown = 50;

	/** 圓下方提示 **/
	private String downNoteText = "大類  金額";

	public Cookie(Context context) {
		super(context);
	}

	public Cookie(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public Cookie(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public String[] getTextValues() {
		return textValues;
	}

	public void setTextValues(String[] textValues) {
		this.textValues = textValues;
	}

	public double[] getNumberValues() {
		return numberValues;
	}

	public void setNumberValues(double[] numberValues) {
		this.numberValues = numberValues;
	}

	public String getNoteText() {
		return noteText;
	}

	public void setNoteText(String noteText) {
		this.noteText = noteText;
	}

	public String getDownNoteText() {
		return downNoteText;
	}

	public void setDownNoteText(String downNoteText) {
		this.downNoteText = downNoteText;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.WHITE);

		getScreenData();
		paint = new Paint();
		canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent,
				paint);
		// 抗鋸齒
		paint.setAntiAlias(true);

		// 實心扇形
		paint.setStyle(Style.FILL);

		// 設定矩形
		getRectF();
		// 得到總資料
		double dsum = getSum();

		getaddy();
		int intlength = numberValues.length;
		float temp = 0;
		float dtemp = 0;
		for (int i = 0; i < intlength; i++) {
			if (numberValues[i] > 0) {
				doDrawTextNote(colors[i], textValues[i], 50, canvas);
				dodrawdegree(canvas, colors[i], temp,
						(float) (numberValues[i] / dsum) * 360);// 畫扇形
				dtemp = temp + (float) (numberValues[i] / dsum) * 360 / 2;
				temp += ((float) (numberValues[i] / dsum) * 360);
			}
		}

		temp = 0;
		dtemp = 0;
		for (int i = 0; i < intlength; i++) {
			if (numberValues[i] > 0) {
				dtemp = temp + (float) (numberValues[i] / dsum) * 360 / 2;
				drawTextdegree(gettempCentalxy(dtemp)[0],
						gettempCentalxy(dtemp)[1],
						(float) (numberValues[i] / dsum) * 360, canvas);
				temp += ((float) (numberValues[i] / dsum) * 360);
			}
		}
		doDrawNote(canvas);
		paint.setTextSize(15);
		canvas.drawText(downNoteText,
				xstartcoordinate - paint.measureText(downNoteText) / 2,
				ystartcoordinate + radius + 25, paint);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		setMeasuredDimension(measureWidth(widthMeasureSpec),
				measureHeight(heightMeasureSpec));
	}

	public void doDrawNote(Canvas canvas) {
		paint.setColor(Color.BLACK);
		paint.setTextSize(20);
		canvas.drawText(noteText, (widthPixels / 2 + marginleft - marginrigth)
				- paint.measureText(noteText) / 2, margintop + 30, paint);
	}

	public double getSum() {
		double tempRtn = 0;
		for (double temp : numberValues) {
			tempRtn += temp;
		}
		return tempRtn;
	}

	public void getRectF() {
		f = new RectF();
		f.set(xstartcoordinate, ystartcoordinate, xendcoordinate,
				yendcoordinate);
		xstartcoordinate = (xstartcoordinate + xendcoordinate) / 2;
		ystartcoordinate = (ystartcoordinate + yendcoordinate) / 2;
		// radius=(xendcoordinate-xstartcoordinate)/2;
	}

	/**
	 * 畫扇形
	 * 
	 * @param canvas
	 * @param name
	 *            顏色
	 * @param startAngle
	 *            開始的度數
	 * @param sweepAngle
	 *            畫多少度
	 */
	public void dodrawdegree(Canvas canvas, int name, float startAngle,
			float sweepAngle) {
		paint.setColor(name);
		canvas.drawArc(f, startAngle, sweepAngle, true, paint);
	}

	public void drawTextdegree(float xtemp, float ytemp, float degree,
			Canvas canvas) {
		paint.setColor(Color.WHITE);
		paint.setTextSize(20);
		
		String strTemp = String.valueOf(Math.round((degree / 360) * 100))+ "%";
		switch (getDirection(xtemp, ytemp)) {

		
		case 0:
			ytemp=ytemp+10f;
			break;
		case 1:
			xtemp=xtemp-paint.measureText(strTemp)/2;
			ytemp=ytemp+10f;
			break;
		case 2:
			xtemp=xtemp-paint.measureText(strTemp)/2;
			break;
		case 3:
			xtemp=xtemp-paint.measureText(strTemp)/2;
			ytemp=ytemp+10f;
			break;
		case 4:
			ytemp=ytemp-10f;
			xtemp=xtemp-paint.measureText(strTemp)/2;
			break;
		case 5:
			ytemp=ytemp+10f;
			xtemp=xtemp-paint.measureText(strTemp)/2;
			break;
		case 6:
			ytemp=ytemp+10f;
			xtemp=xtemp-paint.measureText(strTemp)/2;
			break;
		case 7:
			ytemp=ytemp+10f;
			xtemp=xtemp-paint.measureText(strTemp)/2;
			break;

		default:
			break;
		}
		
		canvas.drawText(strTemp , xtemp, ytemp, paint);
	}

	public float[] gettempCentalxy(float degree) {
		float[] fRtn = { 0.0f, 0.0f };
		float xtemp, ytemp;
//		xtemp = (float) ((xstartcoordinate + xstartcoordinate + radius
//				* Math.cos(degree * (Math.PI / 180))) / 2);
//		ytemp = (float) ((ystartcoordinate + ystartcoordinate + radius
//				* Math.sin(degree * (Math.PI / 180))) / 2);

		xtemp = (float) ((xstartcoordinate + (radius-30)
				* Math.cos(degree * (Math.PI / 180))));
		ytemp = (float) ((ystartcoordinate + (radius-30)
				* Math.sin(degree * (Math.PI / 180))));
		fRtn[0] = xtemp;
		fRtn[1] = ytemp;
		return fRtn;
	}

	public void doDrawTextNote(int color, String text, double number,
			Canvas canvas) {
		paint.setTextSize(15);
		paint.setColor(color);
		canvas.drawRect((widthPixels / 4 * 3), addy + 15 + statar,
				(widthPixels / 4 * 3) + 15.0f, addy + 30 + statar, paint);
		paint.setColor(Color.BLACK);
		canvas.drawText(text, (widthPixels / 4 * 3) + 20.0f,
				addy + 28 + statar, paint);
		statar += 30.0f;
		Logs.v("msg", text);
	}

	public void getaddy() {
		int intlength = 0;
		for (double temp : numberValues) {
			if (temp > 0) {
				intlength++;
			}
		}
		statar = 0;
		Logs.v("msg", "data intlength = " + intlength);
		float temp;
		if (intlength == 1) {
			temp = 15f;
		} else {
			temp = (intlength - 1) * 15f + intlength * 15f;
		}
		addy = ystartcoordinate - temp / 2 - 15f;
	}

	private void getScreenData() {
		DisplayMetrics metrics = getResources().getDisplayMetrics();

		// // 螢幕高
		// heightPixels = metrics.heightPixels;
		// // 螢幕寬
		// widthPixels = metrics.widthPixels;

		// 螢幕高
		heightPixels = getHeight();
		// 螢幕寬
		widthPixels = getWidth();

		marginleft = getPaddingLeft();
		margindown = getPaddingBottom();
		margintop = getPaddingTop();
		marginrigth = getPaddingRight();

		Logs.v("msg", "Cookie heightPixels =" + String.valueOf(heightPixels)
				+ "  widthPixels =" + String.valueOf(widthPixels));
		// 設定x座標起點
		xstartcoordinate = ((widthPixels / 8) * 3 + marginleft - marginrigth)
				- radius;

		// 設定x座標終點
		xendcoordinate = ((widthPixels / 8) * 3 + marginleft - marginrigth)
				+ radius;

		// 設定y座標起點
		ystartcoordinate = (heightPixels / 2 + margintop - margindown) - radius;

		// 設定y座標終點
		yendcoordinate = (heightPixels / 2 + margintop - margindown) + radius;
	}

	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 = metrics.widthPixels / 2 + 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 int getDirection(float xtemp, float ytemp) {

		if (xstartcoordinate < xtemp && ystartcoordinate < ytemp) {
			Log.v("msg", "msg = rightdrown");
			return 7;
		}
		if (xstartcoordinate > xtemp && ystartcoordinate > ytemp) {
			Log.v("msg", "msg = lefttop");
			return 3;
		}
		if (xstartcoordinate > xtemp && ystartcoordinate < ytemp) {
			Log.v("msg", "msg = leftdrown");
			return 5;
		}
		if (xstartcoordinate < xtemp && ystartcoordinate > ytemp) {
			Log.v("msg", "msg = rigthtop");
			return 1;
		}

		if (xstartcoordinate < xtemp && ystartcoordinate == ytemp) {
			Log.v("msg", "msg = Drown");
			return 6;
		}

		if (xstartcoordinate == xtemp && ystartcoordinate < ytemp) {
			Log.v("msg", "msg = rigth");
			return 0;
		}

		if (xstartcoordinate == xtemp && ystartcoordinate > ytemp) {
			Log.v("msg", "msg = top");
			return 2;
		}
		if (xstartcoordinate > xtemp && ystartcoordinate == ytemp) {
			Log.v("msg", "msg = left");
			return 4;
		}
		return 0;
	}
}

不能把全部程式碼粘貼出來望諒解!涉及到公司的利益

用法

 /**波段金額比例**/
 private Cookie mCkAddBangAmount;
 
 /**波段數量比例**/
 private Cookie mCkAddBangQuantity;
 
 /**大類金額比例**/
 private Cookie mCkAddTypeAmount;
 
 /**大類數量比例**/
 private Cookie mCkAddTypeQuantity;
 
 /**預期和實際對比**/
 private LineHistogram mHgAddContrast;


方法操作

public void getAddCookieToBangAmount(){
		SqlStatistics service = new SqlStatistics(getActivity());
		DHHApp.setUserId("J0049");
		ArrayList<OrderStatistics> arrayList = service.getSumAmountForBang(true);
		Logs.v("msg", "test data = " + arrayList.toString());
		String[] datatext = new String[arrayList.size()];
		double[] thinkdata = new double[arrayList.size()];
		int intcount = 0;
		for (OrderStatistics orderStatistics : arrayList) {
			datatext[intcount] = orderStatistics.getShowName();
			thinkdata[intcount]=orderStatistics.getShowNumber();
			intcount++;
		}
		mCkAddBangAmount.setTextValues(datatext);
		mCkAddBangAmount.setNumberValues(thinkdata);
		mCkAddBangAmount.setDownNoteText("波段   金額");
	}
	
	public void getAddCookieToBangQuantity(){
		SqlStatistics service = new SqlStatistics(getActivity());
		DHHApp.setUserId("J0049");
		ArrayList<OrderStatistics> arrayList = service.getSumAmountForBang(true);
		Logs.v("msg", "test data = " + arrayList.toString());
		String[] datatext = new String[arrayList.size()];
		double[] thinkdata = new double[arrayList.size()];
		int intcount = 0;
		for (OrderStatistics orderStatistics : arrayList) {
			datatext[intcount] = orderStatistics.getShowName();
			thinkdata[intcount]=orderStatistics.getShowNumber();
			intcount++;
		}
		mCkAddBangQuantity.setTextValues(datatext);
		mCkAddBangQuantity.setNumberValues(thinkdata);
		mCkAddBangQuantity.setDownNoteText("波段   數量");
	}


檔案佈局

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

                <com.wforyou.dhh.ui.widget.Cookie
                    android:id="@+id/user_cookie_bangAmount"
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent" />

                <com.wforyou.dhh.ui.widget.Cookie
                    android:id="@+id/user_cookie_bangQuantity"
                    android:layout_width="wrap_content"
                    android:layout_toRightOf="@+id/user_cookie_bangAmount"
                    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_bangcontrast" />
            </RelativeLayout>