android刮奖控件,使用简单。

序言:

很多哥们可能不喜欢买彩票,但是小时候肯定都刮过奖,5毛钱一次,今天我们要在android上面实现刮奖的控件。


功能:

奖的生成,刮奖,刮开面积的计算,分享到第三方平台。


效果图:

    


控件代码:

package com.example.xiangpica;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;

import com.example.xiangpica.bean.LotteryInfo;
import com.example.xiangpica.manage.LotteryManage;

public class MyView extends TextView {

	private int widget, height;

	private Context mContext;
	private Paint mPaint;
	private Canvas tempCanvas;
	private Bitmap mBitmap;
	private float x, y, ox, oy;
	private Path mPath;
	Handler mHandler;
	MyThread mThread;

	LotteryInfo info;
	int messageCount;

	int[] pixels;
	
	int color = 0xFFD6D6D6;

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		init(attrs);
	}

	/**
	 * 再一次抽奖
	 */
	public void againLotter() {
		messageCount = 0;
		info = LotteryManage.getRandomLottery();
		tempCanvas.drawColor(color);
		setText(info.getText());
	}

	public LotteryInfo getLotterInfo() {
		return info;
	}

	private void init(AttributeSet attrs) {
		// 获取控件大小值
		TypedArray a = mContext.obtainStyledAttributes(attrs,
				R.styleable.lotter);
		widget = (int) a.getDimension(R.styleable.lotter_widget, 300);
		height = (int) a.getDimension(R.styleable.lotter_height, 100);
		a.recycle();

		// 初始化路径
		mPath = new Path();

		// 初始化画笔
		mPaint = new Paint();
		mPaint.setColor(mContext.getResources().getColor(R.color.view_color));
		mPaint.setAlpha(0);
		mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
		mPaint.setAntiAlias(true);
		mPaint.setStyle(Style.STROKE);
		mPaint.setStrokeWidth(50);//画笔宽度

		// 初始化Bitmap并且锁定到临时画布上
		mBitmap = Bitmap.createBitmap(widget, height, Bitmap.Config.ARGB_4444);
		tempCanvas = new Canvas();
		tempCanvas.setBitmap(mBitmap);
		againLotter();

		// 在字线程中创建Handler接收像素消息
		mThread = new MyThread();
		mThread.start();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 将处理过的bitmap画上去
		canvas.drawBitmap(mBitmap, 0, 0, null);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			touchDown(event);
			break;
		case MotionEvent.ACTION_MOVE:
			touchMove(event);
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			break;
		}
		return true;
	}

	/**
	 *  移动的时候
	 * @param event
	 */
	private void touchMove(MotionEvent event) {
		x = event.getX();
		y = event.getY();
		// 二次贝塞尔,实现平滑曲线;oX, oY为操作点 x,y为终点 
		mPath.quadTo((x + ox) / 2, (y + oy) / 2, x, y);
		tempCanvas.drawPath(mPath, mPaint);
		ox = x;
		oy = y;
		invalidate();
		computeScale();
	}
	/**
	 * 第一次按下来
	 * 
	 * @param event
	 */
	private void touchDown(MotionEvent event) {
		ox = x = event.getX();
		oy = y = event.getY();
		mPath.reset();
		mPath.moveTo(ox, oy);
	}
	/**
	 * 计算百分比
	 */
	private void computeScale() {
		Message msg = mHandler.obtainMessage(0);
		msg.obj = ++messageCount;
		mHandler.sendMessage(msg);
	}
	
	/**
	 * 异步线程,作用是创建handler接收处理消息。
	 * @author Administrator
	 *
	 */
	class MyThread extends Thread {

		public MyThread() {
		}

		@Override
		public void run() {
			super.run();
			/*
			 * 创建 handler前先初始化Looper.
			 */
			Looper.prepare();

			mHandler = new Handler() {
				@Override
				public void dispatchMessage(Message msg) {
					super.dispatchMessage(msg);
					// 只处理最后一次的百分比
					if ((Integer) (msg.obj) != messageCount) {
						return;
					}
					// 取出像素点
					synchronized (mBitmap) {
						if (pixels == null) {
							pixels = new int[mBitmap.getWidth()
									* mBitmap.getHeight()];
						}
						mBitmap.getPixels(pixels, 0, widget, 0, 0, widget,
								height);
					}

					int sum = pixels.length;
					int num = 0;
					for (int i = 0; i < sum; i++) {
						if (pixels[i] == 0) {
							num++;
						}
					}
					info.setScratchPercentage(num / (double) sum);
					System.out.println("百分比:" + info.getScratchPercentage()
							* 100);
				}
			};
			/*
			 * 启动该线程的消息队列
			 */
			Looper.loop();
		}
	}
}


原理介绍:

1、刮彩票的实现,新建一张和控件一样大的Bitmap,然后根据此bitmap新建一个临时画布并设置此bitmap,这样子临时画布做的操作就会更改到这张bitmap上面,然后重写控件的ondraw方法每次都去draw这张bitmap即可。

2、刮开面积的计算,由于bitmap的表面区域随着刮的过程要不断计算太耗时,所以计算面积是异步进行的,再异步线程初始化handler,然后刮开部分有改变就通知handler去计算并发送计算的次数,handler计算的时候会判断是否是最后一次,如果不是就直接不算,这样的好处是刮开的过程中会不断的发送,只有最后一次发送的计算通知是有效的值,计算的原理就是拷贝出bitmap的像素值,然后遍历判断是0的像素点比例(为0的就是透明区域)。

3、奖品生成原理,采用随机数,0~1000,0~9是一等奖(概率1%)10~29是二等奖(概率2%)30~100是三等奖(概率7%)

4、分享控件的原理,博主之前的博客http://blog.csdn.net/panjidong_3/article/details/16943063有详细介绍,很方便直接拿来用。

下载:

刮刮乐http://download.csdn.net/detail/panjidong_3/6703273




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值