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

时间: 2024-08-24 16:05:16

Android 刮刮卡的相关文章

【2014年最后的分享啦】Android实现自定义刮刮卡效果View

一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文<Android实现自定义圆形.圆角和椭圆ImageView(使用Xfermode图形渲染方法)>, 今天我们来看看如何实现电商app里常用到的刮刮卡效果的view组件,其实原理和实现圆角图片的差不多,都是使用Xfermode渲染模式来实现的. (老规矩,源码在博文最后给出哈) 基本原理步骤是这样的

Android 自定义控件实现刮刮卡效果 真的就只是刮刮卡么

很久以前也过一个html5的刮刮卡效果~~上次看到有人写Android的刮刮卡效果~~于是乎产生了本篇博客~~此类例子也比较多了,大家可以百度看看~不过还是通过本例子,带大家发掘一下,里面隐含的知识~ 1.Xfermode以及PorterDuff 如果大家还记得,曾经在博客:完美实现图片圆角和圆形 简单介绍过圆角的实现原理也是基于这个. 首先我们看一下官方的例子,很好的展示了16种Mode的效果: 注:先绘制的Dst,再绘制的Src. 好了,看了这个图,我来问大家几个问题: 问题1.如果我想实现

Android 自己定义控件实现刮刮卡效果 真的就仅仅是刮刮卡么

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40162163 , 本文出自:[张鸿洋的博客] 非常久以前也过一个html5的刮刮卡效果~~上次看到有人写Android的刮刮卡效果~~于是乎产生了本篇博客~~此类样例也比較多了,大家能够百度看看~只是还是通过本样例,带大家发掘一下.里面隐含的知识~ 1.Xfermode以及PorterDuff 假设大家还记得,以前在博客:完美实现图片圆角和圆形 简介过圆角的实现原理也是基于这个

Android 刮刮卡实现效果

实现刮刮卡我们可以Get到哪些技能? * 圆形圆角图片的实现原理 * 双缓冲技术绘图 * Bitmap获取像素值数据 * 获取绘制文本的长宽 * 自定义View的掌握 * 获取屏幕密度 * TypeValue.applyDemension * Canvas的一些绘制方法 * Paint的一些常用的属性 * Path的一些方法 刮刮卡的实现原理图 这里用到了13中模式中的DstOut这种模式. 对于这幅图而言,首先绘制Dst,设置xfermode,再绘制Src. 刮刮卡的实现原理步骤 1.绘制显示

Android 刮刮卡自定义view

import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics

【Android - View】之自定义View实现“刮刮卡”效果

首先来介绍一下这个自定义View: (1)这个自定义View的名字叫做 GuaguakaView ,继承自View类: (2)这个View实现了很多电商项目中的"刮刮卡"的效果,即用户可以刮开覆盖层,查看自己是否中奖: (3)用户可以设置覆盖层的图片以及显示的文本内容和字体大小等参数: (4)用户可以设置一个阈值,当刮开的面积大于这个阈值时,就会自动清除所有覆盖物. 接下来简单介绍一下在这个自定义View中用到的技术点: (1)自定义属性:在 /res/values/attr.xml 

css3 canvas之刮刮卡效果

今天我有时间学习了一下html5新增的这个标签canvas,以前虽然经常写html5网页,可是都没用过这个标签.最近刚弄了一个h5微信送祝福的网页,差不多折腾了一个星期,所以我觉得我得系统的来学习一下html5和css3了. 好了,废话不多说,下面贴出我的代码. 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <ti

用c#开发微信 (16) 微活动 2 刮刮卡

微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公众账号关注.对于企业来说,做微信推广重要的一个方面就是提高用户和公众账号之间的黏度,而微信刮刮卡就是其中最为常见的活动. 下面详细介绍: 一.使用 1. 新建一个刮刮卡的活动: 2. 奖项设置 3. 保存后,在微信里给公众号发一个“刮刮卡”的消息, 就会收到刮刮卡的内容,进入活动后,就可以刮奖了 二

HTML5实现类似刮刮卡的功能

HTML5实现类似刮刮卡的功能 有这样一个功能,当我们使用微信公众号,发送图片时......此处省略300字! 注意要点设置: 1.设置用户缩放:user-scalable=no|yes <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> 2.禁止拖动: docu