好久没有写博客了,今天有正好有时间,接下来为大家带来一款电商中要使用的刮刮卡项目,刮刮卡相信大家小时候都玩过,那个时候,可能大家使用的是小纸片的,现在也可以带大家重温小时候的美好时光,今天将这个刮刮卡的项目分享给大家,希望对大家有学习和工作上的帮助。
一:先上效果图
二:原理分析
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); } }
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
原文地址:http://blog.csdn.net/u011546655/article/details/45173197