序言:

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


功能:

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


效果图:


控件代码:

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之控件EditText学习
  2. Android布局属性补遗
  3. ui布局参数设置
  4. layout_alignParentRight android:paddingRight
  5. Android练习
  6. C虾仔笔记 - EditText编辑框
  7. android 5.0系统 EditText控件
  8. Android布局控件属性
  9. android layout以及一些常用的android控件属性

随机推荐

  1. Android(安卓)Recovery
  2. android 获取路径目录方法以及判断目录是
  3. android内核编译,终于ok了,总结之
  4. TextView中ellipsize属性
  5. Android打开系统设置界面
  6. Android(安卓)数据通信
  7. Android类库介绍
  8. Android启动流程分析(十二) SystemServer
  9. Android深入浅出系列课程---Lesson1 AAF1
  10. Android常见布局简述