1. 程式人生 > >android 自定義view實現圓盤抽獎的效果

android 自定義view實現圓盤抽獎的效果

廢話不多說直接上程式碼。




import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;



public class ZhuanpanView extends View implements OnGlobalLayoutListener {

	private int width; // 轉盤寬度
	private int padding; // 轉盤內邊距
	private int radius;// 半徑
	private RectF rect; // 圓形矩形區域
	private Paint paint; // 圖形畫筆
	private Paint painttext; // 文字畫筆
	private float angle = 0; // 起始旋轉角度
	private int count = 8;// 扇形個數
	private float shanxingangle; // 扇形角度
	private String[] jianzhi = { "謝謝參與", "4999", "200", "50", "500", "9999",
			"100", "500" }; // 價值
	private String[] jianzhimc = { "豆差一點兒", "流量豆", "經驗值", "流量豆", "流量豆", "流量豆",
			"流量豆", "經驗值" }; // 價值名稱
	private float speed = 0; // 每次旋轉角度
	private float decrease = 1;
	private int jg = 50;
	private Handler handler = new Handler();

	public static final int NOMEAL = 0; // 正常狀態
	public static final int ZHUANING = 1; // 正在轉
	public static final int ENDING = 2; // 正在停止
	private int state = NOMEAL;

	private Bitmap backbitmap=BitmapFactory.decodeResource(getResources(), R.drawable.zhuanpanwaiyuan);

	private Runnable runnable = new Runnable() {

		@Override
		public void run() {

			ZhuanpanView.this.invalidate();
			handler.postDelayed(runnable, jg);
		}
	};

	public ZhuanpanView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);

		getViewTreeObserver().addOnGlobalLayoutListener(this);
		padding = getPaddingLeft();
		// 圖形畫筆
		paint = new Paint();
		paint.setAntiAlias(true); // 抗鋸齒
		paint.setStyle(Paint.Style.FILL);
		//設定繪製的顏色,a代表透明度,r,g,b代表顏色值。
		paint.setARGB(255, 14 * 16 + 9, 14 * 16 + 9, 14 * 16 + 9);
		//設定畫筆寬度
		paint.setStrokeWidth(4);

		// 文字畫筆
		painttext = new Paint();
		painttext.setAntiAlias(true); // 抗鋸齒
		//設定繪製文字的字號大小
		painttext.setTextSize(30);
		//設定畫筆的樣式,為FILL,FILL_OR_STROKE,或STROKE Style.FILL: 實心 STROKE:空心 FILL_OR_STROKE:同時實心與空心
		painttext.setStyle(Paint.Style.FILL);
		painttext.setARGB(255, 15 * 16 + 4, 6 * 16 + 12, 10);
		shanxingangle = 360.0f / 8;
	}

	public ZhuanpanView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public ZhuanpanView(Context context) {
		this(context, null);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//計算最小值
		width = Math.min(getMeasuredHeight(), getMeasuredWidth());
		//
		radius = (width - padding * 2) / 2;
		rect = new RectF(padding, padding, width - padding, width - padding);
		setMeasuredDimension(width, width);
	}

	public void StartZhuan(int index) {
		state = ZHUANING;
		// 計算速度
		// 每項角度大小
		float angle = (float) (360 /count);
		// 中獎角度範圍(因為指標向上,所以水平第一項旋轉到指標指向,需要旋轉210-270;)
		float from = 270 - (index + 1) * angle;
		float to = from + angle;
		// 停下來時旋轉的距離
		float targetFrom =  0* 360 + from;
		/**
		 * <pre>
		 *  (v1 + 0) * (v1+1) / 2 = target ;
		 *  v1*v1 + v1 - 2target = 0 ;
		 *  v1=-1+(1*1 + 8 *1 * target)/2;
		 * </pre>
		 */
		float v1 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetFrom) - 1) / 2;
		float targetTo = 0 * 360 + to;
		float v2 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetTo) - 1) / 2;

		speed = (float) (v1 + Math.random() * (v2 - v1));
		Log.v("speed",""+speed);
		//speed = 30;
	}

	public void EndZhuan() {

		state = ENDING;
		angle=0;
	}

	public int getState() {
		return state;
	}

	public boolean isZhan() {

		return speed != 0;
	}

	@Override
	protected void onDraw(Canvas canvas) {

		angle += speed;
		if (angle >= 360) {
			angle -= 360;
		}
		// 點選停止
		if (state == ENDING) {

			speed -= decrease; // 速度的減少量

		}
		if (speed <= 0) {
			speed = 0;
			state = NOMEAL;
		}
		//繪製背景
		paint.setARGB(80, 13 * 16 + 12, 13 * 16 + 12, 13 * 16 + 12);

		//展示在螢幕上的區域
		canvas.drawBitmap(backbitmap, null, new Rect(padding / 2,
				padding / 2, getMeasuredWidth() - padding / 2,
				getMeasuredWidth() - padding / 2), null);
		//canvas.drawCircle(radius + padding, radius + padding, radius, paint);
		// 繪製扇形
		paint.setARGB(255, 13 * 16 + 12, 13 * 16 + 12, 13 * 16 + 12);
		paint.setStyle(Paint.Style.STROKE);
		float vOffset = 0;
		float hOffset = 0;
		float textwidth = 0;
		for (int i = 0; i < count; i++) {
			float startangle = i * shanxingangle + angle;
			canvas.drawArc(rect, startangle, shanxingangle, true, paint);
			// 繪製文字
			Path path = new Path();
			path.addArc(rect, startangle, shanxingangle);
			// 計算文字
			painttext.setTextSize(35);
			painttext.setStyle(Paint.Style.FILL);
			painttext.setARGB(255, 15 * 16 + 4, 6 * 16 + 12, 10);
			textwidth = painttext.measureText(jianzhi[i]);
			vOffset = radius / 5;
			hOffset = (float) (radius * Math.PI / count - textwidth / 2);
			canvas.drawTextOnPath(jianzhi[i], path, hOffset, vOffset, painttext);
			painttext.setTextSize(30);
			painttext.setStyle(Paint.Style.FILL);
			painttext.setARGB(255, 9 * 16 + 12, 9 * 16 + 12, 9 * 16 + 12);
			textwidth = painttext.measureText(jianzhimc[i]);
			hOffset = (float) (radius * Math.PI / count - textwidth / 2);
			canvas.drawTextOnPath(jianzhimc[i], path, hOffset, vOffset + 30,
					painttext);
		}
	}

	@Override
	public void onGlobalLayout() {
		// 如果整個佈局完成啟動handler
		getViewTreeObserver().removeGlobalOnLayoutListener(this);
		handler.postDelayed(runnable, jg);
	}
}

Activity中的一些邏輯


import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

	// 逗你轉
	private Button btn_zhan;
	private ZhuanpanView zview;



	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		zview =  this.findViewById(R.id.zview);
		btn_zhan = this.findViewById(R.id.btn_zhan);
		btn_zhan.setOnClickListener(this);
	}
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
			case R.id.btn_zhan:
				//判斷是否為正常狀態
				if (zview.getState() == ZhuanpanView.NOMEAL) {
					//開始轉動
					zview.StartZhuan(1);
					//給按鈕換一個背景
					btn_zhan.setBackgroundResource(R.drawable.icon_end);
				} else {
					//判斷是否為正在轉
					if (zview.getState() == ZhuanpanView.ZHUANING) {
						//停止
						zview.EndZhuan();
						btn_zhan.setBackgroundResource(R.drawable.icon_bengin);
					}
				}
				break;
		}

	}


}

佈局程式碼就是一個button加一個背景圖片。