序言:

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


功能:

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


效果图:

android刮奖控件,使用简单。_第1张图片android刮奖控件,使用简单。_第2张图片android刮奖控件,使用简单。_第3张图片android刮奖控件,使用简单。_第4张图片


控件代码:

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();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 将处理过的bitmap画上去canvas.drawBitmap(mBitmap, 0, 0, null);}@Overridepublic 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() {}@Overridepublic void run() {super.run();/* * 创建 handler前先初始化Looper. */Looper.prepare();mHandler = new Handler() {@Overridepublic 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. android 5.0系统 EditText控件
  2. Android/java 多线程(五)-ThreadPoolExecutor线程池的使用
  3. android layout以及一些常用的android控件属性
  4. Android 线程池来管理线程
  5. Android的线程使用来更新UI----Thread、Handler、Looper、TimerT
  6. Android关于线程更新UI的方法
  7. Android,UI主线程与子线程
  8. 解析Android中的main线程与子线程
  9. Android 线程优先级设置方法

随机推荐

  1. Android设计分辨率
  2. android 开发 socket发送会有部分乱码,串
  3. Android(安卓)O 行为变更
  4. Android里面如何编写退出主程序的提示代
  5. RecyclerView的功能扩展(Android图片选择
  6. Android(安卓)中UI与耗时操作的分离
  7. Android实习生首次面试总结
  8. 自定义View 篇一--------《自定义View流
  9. Android(安卓)中自定义组件例子一(中级)
  10. Android数据加密DES、3DES、AES