android刮奖控件,使用简单

来源:互联网 发布:小白源码论坛 编辑:程序博客网 时间:2024/05/15 03:10

序言:

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


功能:

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


效果图:

    


控件代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.example.xiangpica;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.Paint;  
  8. import android.graphics.Paint.Style;  
  9. import android.graphics.Path;  
  10. import android.graphics.PorterDuff.Mode;  
  11. import android.graphics.PorterDuffXfermode;  
  12. import android.os.Handler;  
  13. import android.os.Looper;  
  14. import android.os.Message;  
  15. import android.util.AttributeSet;  
  16. import android.view.MotionEvent;  
  17. import android.widget.TextView;  
  18.   
  19. import com.example.xiangpica.bean.LotteryInfo;  
  20. import com.example.xiangpica.manage.LotteryManage;  
  21.   
  22. public class MyView extends TextView {  
  23.   
  24.     private int widget, height;  
  25.   
  26.     private Context mContext;  
  27.     private Paint mPaint;  
  28.     private Canvas tempCanvas;  
  29.     private Bitmap mBitmap;  
  30.     private float x, y, ox, oy;  
  31.     private Path mPath;  
  32.     Handler mHandler;  
  33.     MyThread mThread;  
  34.   
  35.     LotteryInfo info;  
  36.     int messageCount;  
  37.   
  38.     int[] pixels;  
  39.       
  40.     int color = 0xFFD6D6D6;  
  41.   
  42.     public MyView(Context context, AttributeSet attrs) {  
  43.         super(context, attrs);  
  44.         mContext = context;  
  45.         init(attrs);  
  46.     }  
  47.   
  48.     /** 
  49.      * 再一次抽奖 
  50.      */  
  51.     public void againLotter() {  
  52.         messageCount = 0;  
  53.         info = LotteryManage.getRandomLottery();  
  54.         tempCanvas.drawColor(color);  
  55.         setText(info.getText());  
  56.     }  
  57.   
  58.     public LotteryInfo getLotterInfo() {  
  59.         return info;  
  60.     }  
  61.   
  62.     private void init(AttributeSet attrs) {  
  63.         // 获取控件大小值  
  64.         TypedArray a = mContext.obtainStyledAttributes(attrs,  
  65.                 R.styleable.lotter);  
  66.         widget = (int) a.getDimension(R.styleable.lotter_widget, 300);  
  67.         height = (int) a.getDimension(R.styleable.lotter_height, 100);  
  68.         a.recycle();  
  69.   
  70.         // 初始化路径  
  71.         mPath = new Path();  
  72.   
  73.         // 初始化画笔  
  74.         mPaint = new Paint();  
  75.         mPaint.setColor(mContext.getResources().getColor(R.color.view_color));  
  76.         mPaint.setAlpha(0);  
  77.         mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  
  78.         mPaint.setAntiAlias(true);  
  79.         mPaint.setStyle(Style.STROKE);  
  80.         mPaint.setStrokeWidth(50);//画笔宽度  
  81.   
  82.         // 初始化Bitmap并且锁定到临时画布上  
  83.         mBitmap = Bitmap.createBitmap(widget, height, Bitmap.Config.ARGB_4444);  
  84.         tempCanvas = new Canvas();  
  85.         tempCanvas.setBitmap(mBitmap);  
  86.         againLotter();  
  87.   
  88.         // 在字线程中创建Handler接收像素消息  
  89.         mThread = new MyThread();  
  90.         mThread.start();  
  91.     }  
  92.   
  93.     @Override  
  94.     protected void onDraw(Canvas canvas) {  
  95.         super.onDraw(canvas);  
  96.         // 将处理过的bitmap画上去  
  97.         canvas.drawBitmap(mBitmap, 00null);  
  98.     }  
  99.   
  100.     @Override  
  101.     public boolean onTouchEvent(MotionEvent event) {  
  102.         int action = event.getAction();  
  103.         switch (action) {  
  104.         case MotionEvent.ACTION_DOWN:  
  105.             touchDown(event);  
  106.             break;  
  107.         case MotionEvent.ACTION_MOVE:  
  108.             touchMove(event);  
  109.             break;  
  110.         case MotionEvent.ACTION_CANCEL:  
  111.         case MotionEvent.ACTION_UP:  
  112.             break;  
  113.         }  
  114.         return true;  
  115.     }  
  116.   
  117.     /** 
  118.      *  移动的时候 
  119.      * @param event 
  120.      */  
  121.     private void touchMove(MotionEvent event) {  
  122.         x = event.getX();  
  123.         y = event.getY();  
  124.         // 二次贝塞尔,实现平滑曲线;oX, oY为操作点 x,y为终点   
  125.         mPath.quadTo((x + ox) / 2, (y + oy) / 2, x, y);  
  126.         tempCanvas.drawPath(mPath, mPaint);  
  127.         ox = x;  
  128.         oy = y;  
  129.         invalidate();  
  130.         computeScale();  
  131.     }  
  132.     /** 
  133.      * 第一次按下来 
  134.      *  
  135.      * @param event 
  136.      */  
  137.     private void touchDown(MotionEvent event) {  
  138.         ox = x = event.getX();  
  139.         oy = y = event.getY();  
  140.         mPath.reset();  
  141.         mPath.moveTo(ox, oy);  
  142.     }  
  143.     /** 
  144.      * 计算百分比 
  145.      */  
  146.     private void computeScale() {  
  147.         Message msg = mHandler.obtainMessage(0);  
  148.         msg.obj = ++messageCount;  
  149.         mHandler.sendMessage(msg);  
  150.     }  
  151.       
  152.     /** 
  153.      * 异步线程,作用是创建handler接收处理消息。 
  154.      * @author Administrator 
  155.      * 
  156.      */  
  157.     class MyThread extends Thread {  
  158.   
  159.         public MyThread() {  
  160.         }  
  161.   
  162.         @Override  
  163.         public void run() {  
  164.             super.run();  
  165.             /* 
  166.              * 创建 handler前先初始化Looper. 
  167.              */  
  168.             Looper.prepare();  
  169.   
  170.             mHandler = new Handler() {  
  171.                 @Override  
  172.                 public void dispatchMessage(Message msg) {  
  173.                     super.dispatchMessage(msg);  
  174.                     // 只处理最后一次的百分比  
  175.                     if ((Integer) (msg.obj) != messageCount) {  
  176.                         return;  
  177.                     }  
  178.                     // 取出像素点  
  179.                     synchronized (mBitmap) {  
  180.                         if (pixels == null) {  
  181.                             pixels = new int[mBitmap.getWidth()  
  182.                                     * mBitmap.getHeight()];  
  183.                         }  
  184.                         mBitmap.getPixels(pixels, 0, widget, 00, widget,  
  185.                                 height);  
  186.                     }  
  187.   
  188.                     int sum = pixels.length;  
  189.                     int num = 0;  
  190.                     for (int i = 0; i < sum; i++) {  
  191.                         if (pixels[i] == 0) {  
  192.                             num++;  
  193.                         }  
  194.                     }  
  195.                     info.setScratchPercentage(num / (double) sum);  
  196.                     System.out.println("百分比:" + info.getScratchPercentage()  
  197.                             * 100);  
  198.                 }  
  199.             };  
  200.             /* 
  201.              * 启动该线程的消息队列 
  202.              */  
  203.             Looper.loop();  
  204.         }  
  205.     }  
  206. }  


原理介绍:

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

0 0