码迷,mamicode.com
首页 > 移动开发 > 详细

Android 刮刮卡

时间:2015-04-21 22:54:52      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:android   刮刮卡   源码   异步线程   

       好久没有写博客了,今天有正好有时间,接下来为大家带来一款电商中要使用的刮刮卡项目,刮刮卡相信大家小时候都玩过,那个时候,可能大家使用的是小纸片的,现在也可以带大家重温小时候的美好时光,今天将这个刮刮卡的项目分享给大家,希望对大家有学习和工作上的帮助。


一:先上效果图


技术分享

技术分享

技术分享


二:原理分析

1.创建一张你想要的bitmap大小,然后根据bitmap的大小,绘制一张画布在上面,然后重写onDraw()方法

2.在刮开面积的不断扩张中,计算扩张面的面积大小,当面积超过60%的时候,就清楚图层

3.下面的刮刮卡信息,可以利用java中的随机数做,可以其是900的倍数什么的,才中奖,这个随意发挥


三:源码示例


自定义控件代码:

package com.zengtao.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * 刮刮卡
 * 
 * @author zengtao 2015年4月17日 上午11:13:46
 */
@SuppressLint("DrawAllocation")
public class GuaGuaKa extends View {

	// -------1.遮盖层的东西
	private int lastX;
	private int lastY;
	private int height = 300;
	private int width = 120;
	private int movingX;
	private int movingY;
	private Bitmap mBitmap;
	private Paint mPaint;
	private Canvas mCanvas;
	private Path mPath;

	// --------2.遮盖层下的东西
	private String mText;
	private Paint mTextPaint;
	private int mTextSize;
	private Rect mRectBounds; // 获取刮刮奖信息的宽和高

	private int[] mPixels;
	private volatile boolean isComlemete = false;
	private Message msg;

	private setOnGuaGuaComplemeteListener mGuaGuaComplemeteListener;

	public void setOnGuaGuaComplemeteListener(
			setOnGuaGuaComplemeteListener mGuaGuaComplemeteListener) {
		this.mGuaGuaComplemeteListener = mGuaGuaComplemeteListener;
	}

	public GuaGuaKa(Context context) {
		super(context);
		init(context);
	}

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

	@SuppressLint("DrawAllocation")
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 1.1获取高度和宽度
		width = MeasureSpec.getSize(widthMeasureSpec);
		height = MeasureSpec.getSize(heightMeasureSpec);
		// 1.2获取宽高在初始化Bitmap
		mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		mCanvas = new Canvas(mBitmap);
		// 1.3设置绘制path画笔的属性
		setPath();

		// 2.1 设置textPaint属性
		setTextMessagePaint();
		mCanvas.drawColor(Color.parseColor("#C7C7C7"));
	}

	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		movingX = (int) event.getX();
		movingY = (int) event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			touchDown(event);
			break;
		case MotionEvent.ACTION_MOVE:
			touchMove(event);
			break;
		case MotionEvent.ACTION_UP:
			touchUp(event);
			break;
		default:
			break;
		}
		invalidate();
		return true;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawText(mText, getWidth() / 2 - mRectBounds.width() / 2,
				getHeight() / 2 + mRectBounds.height() / 2, mTextPaint);
		if (!isComlemete) {
			drawPath();
			canvas.drawBitmap(mBitmap, 0, 0, null);
		}
	}

	// 画path
	private void drawPath() {
		mPaint.setXfermode(new PorterDuffXfermode(
				android.graphics.PorterDuff.Mode.DST_OUT));
		mCanvas.drawPath(mPath, mPaint);
	}

	// 手势抬起
	private void touchUp(MotionEvent event) {
		new Thread(mRunnable).start();
	}

	// 手势放下
	private void touchMove(MotionEvent event) {
		int dx = Math.abs(movingX - lastX);
		int dy = Math.abs(movingY - lastY);
		if (dx > 3 || dy > 3) {
			mPath.lineTo(movingX, movingY);
		}
		lastX = movingX;
		lastY = movingY;
	}

	// 手势按下
	private void touchDown(MotionEvent event) {
		lastX = movingX;
		lastY = movingY;
		mPath.moveTo(lastX, lastY);
	}

	/**
	 * 设置绘制path画笔的属性
	 */
	private void setPath() {
		mPaint.setColor(Color.parseColor("#c0c0c0"));
		mPaint.setAntiAlias(true);
		mPaint.setDither(true);
		mPaint.setStrokeJoin(Paint.Join.ROUND);
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(40);
	}

	/**
	 * 设置画刮刮卡画笔的属性
	 */
	private void setTextMessagePaint() {
		mTextPaint.setColor(Color.DKGRAY);
		mTextPaint.setTextSize(mTextSize);
		mTextPaint.setStyle(Style.FILL);
		// 获取的当前画笔绘制文本的宽和高
		mTextPaint.getTextBounds(mText, 0, mText.length(), mRectBounds);
	}

	/**
	 * 初始化
	 * 
	 * @param context
	 */
	private void init(Context context) {
		// ----1.遮盖层
		mPaint = new Paint();
		mPath = new Path();
		// ----2.遮盖层下的内容
		mTextPaint = new Paint();
		mRectBounds = new Rect();
		mText = "谢谢惠顾";
		mTextSize = 40;
	}

	/**
	 * 开启线程计算用户擦除了多少区域
	 */
	private Runnable mRunnable = new Runnable() {

		@Override
		public void run() {
			int w = getWidth();
			int h = getHeight();

			float wipeArea = 0;
			float totalArea = w * h;
			Bitmap bitmap = mBitmap;

			if (mPixels == null) {
				mPixels = new int[w * h];
			}
			// 获取bitmap上所有的像素信息
			bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);

			for (int i = 0; i < w; i++) {
				for (int j = 0; j < h; j++) {
					int index = i + j * w;
					if (mPixels[index] == 0) {
						wipeArea++;
					}
				}
			}

			if (wipeArea > 0 && totalArea > 0) {
				int percent = (int) (wipeArea * 100 / totalArea);
				Log.e("System.out", "区域---" + percent);
				// 清楚图层区域
				if(percent > 60) {
					isComlemete = true;
					postInvalidate();
				}
				// 如果用户在调用Toast的时候,不能再子线程中做,这样的情况是属于在子线程中跟新ui,所以用handle在主线程中操作
				msg = mHandler.obtainMessage();
				msg.what = 0x1;
				msg.arg1 = percent;
				mHandler.sendMessage(msg);
			}
		}
	};

	@SuppressLint("HandlerLeak")
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (mGuaGuaComplemeteListener != null) {
				int percent = msg.arg1;
				if (percent < 60) {
					mGuaGuaComplemeteListener.notEnough("亲,您在刮点吧,还不够! 55555");
				} else {
					mGuaGuaComplemeteListener.complemete(mText);
				}
			}
		};
	};

	public interface setOnGuaGuaComplemeteListener {
		void complemete(String result);

		void notEnough(String result);
	}
}


二:MainActivity中的实现

package com.zengtao.testdemo;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;

import com.zengtao.view.GuaGuaKa;
import com.zengtao.view.GuaGuaKa.setOnGuaGuaComplemeteListener;

public class MainActivity extends Activity {
	private GuaGuaKa mGuaGuaKa;
	private Button reStart;

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

		mGuaGuaKa = (GuaGuaKa) findViewById(R.id.scratch);
		reStart = (Button) findViewById(R.id.reStart);
		mGuaGuaKa.setOnGuaGuaComplemeteListener(new setOnGuaGuaComplemeteListener() {

			@Override
			public void complemete(String result) {
				Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)
						.show();
			}

			@Override
			public void notEnough(String result) {
				Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT)
				.show();
			}
		});
	}
}


四:以上便可以完成刮刮卡的实现,看着还是挺简单的,那么你也来试一试吧,蚊子虽小,却也是肉,来拿吧


Demo下载地址:http://download.csdn.net/detail/u011546655/8617235


Android 刮刮卡

标签:android   刮刮卡   源码   异步线程   

原文地址:http://blog.csdn.net/u011546655/article/details/45173197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!