ScratchCardView.class package com.hbz.core.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.hbz.core.R; public class ScratchCardView extends View { protected int textColor; protected int coatingColor; protected float textSize; protected float eraserSize; protected String text; protected Path path; protected int width; protected int height; protected Bitmap coatingBitmap; protected Canvas coatingCanvas; protected Paint textPaint; protected Paint eraserPaint; protected float pointX; protected float pointY; protected boolean isComplete; private float percentage; private Bitmap backgroundBitmap; private Matrix matrix; public ScratchCardView(Context context) { this(context, null); } public ScratchCardView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ScratchCardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ScratchCardView); textColor = array.getColor(R.styleable.ScratchCardView_textColor, Color.BLACK); coatingColor = array.getColor(R.styleable.ScratchCardView_coatingColor, Color.GRAY); textSize = array.getDimension(R.styleable.ScratchCardView_textSize, 25); eraserSize = array.getDimension(R.styleable.ScratchCardView_eraserSize, 20); text = array.getString(R.styleable.ScratchCardView_text); percentage = array.getFloat(R.styleable.ScratchCardView_percentage, 70); BitmapDrawable backgroundImg = (BitmapDrawable) array.getDrawable(R.styleable.ScratchCardView_backgroundImg); if (backgroundImg != null) { backgroundBitmap = backgroundImg.getBitmap(); } array.recycle(); initPaint(); } protected void initPaint() { textPaint = new Paint(); textPaint.setAntiAlias(true); textPaint.setStyle(Paint.Style.FILL); textPaint.setStrokeWidth(20); textPaint.setTextSize(textSize); textPaint.setDither(true); textPaint.setColor(textColor); eraserPaint = new Paint(); eraserPaint.setAntiAlias(true); eraserPaint.setStyle(Paint.Style.STROKE); eraserPaint.setStrokeWidth(10); eraserPaint.setTextSize(eraserSize); eraserPaint.setDither(true); path = new Path(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; initBackground(); coatingBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); coatingCanvas = new Canvas(coatingBitmap); coatingCanvas.drawColor(coatingColor); } @Override public void draw(Canvas canvas) { if (backgroundBitmap != null) { canvas.drawBitmap(backgroundBitmap, matrix, null); } drawText(canvas); if (!isComplete) { drawPath(); canvas.drawBitmap(coatingBitmap, 0, 0, null); } super.draw(canvas); } protected void initBackground() { matrix = new Matrix(); float bitmapWidth = backgroundBitmap.getWidth(); float bitmapHeight = backgroundBitmap.getHeight(); float scaleX = width / bitmapWidth; float scaleY = height / bitmapHeight; matrix.setScale(scaleX, scaleY); } private void drawPath() { //在涂层和path相交的地方,根据涂层的alpha进行过滤, eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); coatingCanvas.drawPath(path, eraserPaint); } protected void drawText(Canvas canvas) { Rect rect = new Rect(); textPaint.getTextBounds(text, 0, text.length(), rect); int textWidth = rect.width(); int textHeight = rect.height(); float x = width / 2 - textWidth / 2; float y = height / 2 + textHeight / 2; canvas.drawText(text, x, y, textPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: float downX = event.getX(); float downY = event.getY(); path.moveTo(downX, downY); invalidate(); pointX = downX; pointY = downY; break; case MotionEvent.ACTION_MOVE: float moveX = event.getX(); float moveY = event.getY(); path.quadTo(pointX, pointY, moveX, moveY); invalidate(); pointX = moveX; pointY = moveY; break; case MotionEvent.ACTION_UP: new Thread(mRunnable).start(); break; } return true; } // 统计刮开的区域 private Runnable mRunnable = new Runnable() { private int[] mPixels; @Override public void run() { int w = getWidth(); int h = getHeight(); float wipeArea = 0; float totalArea = w * h; Bitmap bitmap = coatingBitmap; 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); if (percent > percentage) { isComplete = true; postInvalidate(); } } } }; }
attr.xml 中添加
<declare-styleable name="ScratchCardView"> <attr name="text" format="string" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color" /> <attr name="coatingColor" format="color" /> <attr name="eraserSize" format="dimension" /> <attr name="percentage" format="float" /> <attr name="backgroundImg" format="reference" /> </declare-styleable>
布局中引用
<com.hbz.core.widget.ScratchCardView android:layout_width="120dp" android:layout_height="30dp" app:backgroundImg="@mipmap/delta" app:coatingColor="@color/rule_gray_hint" app:eraserSize="20dp" app:percentage="70" app:text="恭喜中奖" app:textColor="@color/color_red" app:textSize="14sp" />