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;
	}
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值