直接上效果图


功能特色:

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);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mCanvas.drawPath(mPath, mPaint);canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);}@Overrideprotected 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();}@Overridepublic 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() {@Overridepublic 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);}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();mRun = false;}}

更多相关文章

  1. Android(安卓)Studio中使用simpleUML绘制类图详细使用及说明
  2. Android(安卓)中显示 Gif 格式图
  3. android paint类
  4. Android的手势的保存
  5. Android(安卓)P在绘制界面时,默认更换skiagl绘图库绘制界面
  6. android canvas 绘制bitmap并保存到本地
  7. android自定义View-垂直滚动的TextView
  8. Android麦克风录音带音量大小动态显示的圆形自定义View
  9. Android(安卓)OpenGL 文本显示 LabelMaker

随机推荐

  1. android ICS 4.0.3 报 java.lang.Illegal
  2. Android 网络通信框架Volley简介(Google
  3. Android(安卓)播放SD卡上指定的一首歌(初
  4. Android中的异常处理 CrashHandler
  5. android 被强制横屏,Activity重启问题解决
  6. 【React Native开发】React Native For A
  7. ImageButton和Button区别
  8. Android(java)学习笔记94:关于广播接收者的
  9. No resource identifier found for attri
  10. Android的Service总结