直接拿来用的Android刮奖控件

 更新时间:2016年09月05日 15:47:39   作者:cmeiyuan  
这篇文章主要为大家分享了可以直接拿来用的Android刮奖控件,非常棒的刮奖控件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

直接上效果图

 

功能特色:
 1、可以设置刮开后显示文字或图片
 2、可以统计已刮开区域所占百分比 

Demo下载地址:RubberDemo.rar 

下面是源码: 

@SuppressLint("HandlerLeak")
public class RubberView extends TextView {

 private static final int W = 480;
 private static final int H = 800;
 private static final int MV = 1;
 private static final int SW = 50;
 private static final int MC = 0xFFD6D6D6;

 private int mWidth;
 private int mHeight;
 private int mMaskColor;
 private int mStrokeWidth;
 private float mX;
 private float mY;
 private boolean mRun;
 private boolean caculate;
 private Path mPath;
 private Paint mPaint;
 private Paint mBitmapPaint;
 private Canvas mCanvas;
 private Bitmap mBitmap;
 private int[] mPixels;
 private Thread mThread;
 private onWipeListener mWipeListener;

 public RubberView(Context context) {
 super(context);
 init(context);
 }

 public RubberView(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(context);
 }

 private final void init(Context context) {
 mMaskColor = MC;
 mStrokeWidth = SW;

 mPath = new Path();
 mBitmapPaint = new Paint();

 mPaint = new Paint();
 mPaint.setAntiAlias(true);// 抗锯齿
 mPaint.setDither(true);// 递色
 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
 mPaint.setStyle(Paint.Style.STROKE);
 mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圆角
 mPaint.setStrokeCap(Paint.Cap.ROUND); // 后圆角
 mPaint.setStrokeWidth(mStrokeWidth); // 笔宽

 mBitmap = Bitmap.createBitmap(W, H, Config.ARGB_8888);
 mCanvas = new Canvas(mBitmap);
 mCanvas.drawColor(mMaskColor);

 mRun = true;
 mThread = new Thread(mRunnable);
 mThread.start();

 setGravity(Gravity.CENTER);
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 mCanvas.drawPath(mPath, mPaint);
 canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int w = MeasureSpec.getSize(widthMeasureSpec);
 int h = MeasureSpec.getSize(heightMeasureSpec);
 if (w > 0 && h > 0) {
  mWidth = w;
  mHeight = h;
 }
 }

 public void reset() {
 mPath.reset();
 mCanvas.drawPaint(mPaint);
 mCanvas.drawColor(mMaskColor);
 invalidate();
 }

 public void setOnWipeListener(onWipeListener listerer) {
 this.mWipeListener = listerer;
 }

 public void setStrokeWidth(int width) {
 this.mStrokeWidth = width;
 mPaint.setStrokeWidth(width);
 }

 public void setMaskColor(int color) {
 this.mMaskColor = color;
 reset();
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 boolean invalidate = false;
 boolean consume = false;
 int action = event.getAction();
 switch (action) {
 case MotionEvent.ACTION_DOWN:
  consume = true;
  touchDown(event);
  break;
 case MotionEvent.ACTION_MOVE:
  consume = true;
  invalidate = touchMove(event);
  break;
 case MotionEvent.ACTION_UP:
  consume = true;
  touchUp(event);
  break;
 }

 if (invalidate) {
  invalidate();
 }

 if (consume) {
  return true;
 }

 return super.onTouchEvent(event);
 }

 // 手指点下屏幕时调用
 private void touchDown(MotionEvent event) {
 caculate = false;
 // 重置绘制路线,即隐藏之前绘制的轨迹
 mPath.reset();
 float x = event.getX();
 float y = event.getY();

 mX = x;
 mY = y;
 // mPath绘制的绘制起点
 mPath.moveTo(x, y);
 }

 // 手指在屏幕上滑动时调用
 private boolean touchMove(MotionEvent event) {
 caculate = false;
 final float x = event.getX();
 final float y = event.getY();

 final float previousX = mX;
 final float previousY = mY;

 // 设置贝塞尔曲线的操作点为起点和终点的一半
 float cX = (x + previousX) / 2;
 float cY = (y + previousY) / 2;

 final float dx = Math.abs(x - previousX);
 final float dy = Math.abs(y - previousY);

 boolean move = false;

 if (dx >= MV || dy >= MV) {
  // 二次贝塞尔,实现平滑曲线;cX, cY为操作点 x,y为终点
  mPath.quadTo(cX, cY, x, y);

  // 第二次执行时,第一次结束调用的坐标值将作为第二次调用的初始坐标值
  mX = x;
  mY = y;

  move = true;
 }
 return move;
 }

 private void touchUp(MotionEvent event) {
 caculate = true;
 mRun = true;
 }

 private Runnable mRunnable = new Runnable() {

 @Override
 public void run() {

  while (mRun) {

  SystemClock.sleep(100);

  // 收到计算命令,立即开始计算
  if (caculate) {

   caculate = false;

   int w = mWidth;
   int h = mHeight;

   float wipeArea = 0;
   float totalArea = w * h;

   // 计算耗时100毫秒左右
   Bitmap bitmap = mBitmap;

   if (mPixels == null) {
   mPixels = new int[w * h];
   }

   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);
   Message msg = mHandler.obtainMessage();
   msg.what = 0x1;
   msg.arg1 = percent;
   mHandler.sendMessage(msg);
   }

  }

  }

 }
 };

 private Handler mHandler = new Handler() {
 public void handleMessage(Message msg) {

  if (mWipeListener != null) {
  int percent = msg.arg1;
  mWipeListener.onWipe(percent);
  }

 };
 };

 public interface onWipeListener {
 public void onWipe(int percent);
 }
 
 @Override
 protected void onDetachedFromWindow() {
 super.onDetachedFromWindow();
 mRun = false;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android中如何取消listview的点击效果

    Android中如何取消listview的点击效果

    这篇文章主要介绍了 Android中取消listview的点击效果的实现方法,通过引用transparent之后会让点击效果透明化,一起通过本文学习吧
    2017-01-01
  • OpenGL ES着色器使用详解(二)

    OpenGL ES着色器使用详解(二)

    这篇文章主要为大家详细介绍了OpenGL ES着色器的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Android studio 禁用AndroidX方式

    Android studio 禁用AndroidX方式

    这篇文章主要介绍了Android studio 禁用AndroidX方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Android中库项目的使用方法图文介绍

    Android中库项目的使用方法图文介绍

    类似开发其他Java应用一样,我们可以将可复用的代码,打成一个jar包,供所有需要的项目使用。这样,可以解决很大一部分代码复用的问题,本文将详细介绍,需要了解的朋友可以参考下
    2012-12-12
  • 解析:继承ViewGroup后的子类如何重写onMeasure方法

    解析:继承ViewGroup后的子类如何重写onMeasure方法

    本篇文章是对继承ViewGroup后的子类如何重写onMeasure方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Android编程实现控件不同状态文字显示不同颜色的方法

    Android编程实现控件不同状态文字显示不同颜色的方法

    这篇文章主要介绍了Android编程实现控件不同状态文字显示不同颜色的方法,涉及Android针对控件布局文件属性设置及状态判定等相关技巧,需要的朋友可以参考下
    2016-02-02
  • Android如何获取子View的位置及坐标详解

    Android如何获取子View的位置及坐标详解

    这篇文章主要给大家介绍了关于Android如何获取子View的位置及坐标的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Android开发中Looper.prepare()和Looper.loop()

    Android开发中Looper.prepare()和Looper.loop()

    Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,具体调用方法大家可以通过本文学习
    2016-11-11
  • Android自定义APP全局悬浮按钮

    Android自定义APP全局悬浮按钮

    这篇文章主要为大家详细介绍了Android自定义APP全局悬浮按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Android实现图片上传功能

    Android实现图片上传功能

    这篇文章主要为大家详细介绍了Android实现图片上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02

最新评论