想法:利用Bitmap做刮奖区的蒙版,利用paint将手指触摸过的区域置为透明,即可显示最先draw过的文字或者图片。
1.自定义View
package com.example.administrator.scratchcards; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Created by Administrator on 2016/9/30. */ public class ScratchView extends View { private float TOUCH_TOLERANCE; // 填充距离,使线条更自然,柔和,值越小,越柔和。 // private final int bgColor; // 位图 private Bitmap mBitmap; private Bitmap mCoverBitmap; //覆盖图 刮奖钱的页面 // 画布 private Canvas mCanvas; // 画笔 private Paint mPaint; private Path mPath; private float mX, mY; private Paint mTextPaint; private final int TEXT_SIZE = 60; private String mText; private boolean isDraw = false; private int WIDTH; private int HEIGHT; private int openSize; private Context mContext; private boolean mHasOpen = false; public ScratchView(Context context) { super(context); init(context); } public ScratchView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public ScratchView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public void init(Context context){ mContext = context; //由于我们无法在代码里直接对资源文件作修改,故需要得到资源文件的副本 mCoverBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.im1).copy(Bitmap.Config.ARGB_8888, true); mBitmap = Bitmap.createBitmap(mCoverBitmap.getWidth(),mCoverBitmap.getHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); WIDTH = mBitmap.getWidth(); HEIGHT = mBitmap.getHeight(); mCanvas.drawBitmap(mCoverBitmap, 0, 0, new Paint()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (isDraw) { canvas.drawText(mText, (mCoverBitmap.getWidth() - TEXT_SIZE * mText.length()) / 2, (mCoverBitmap.getHeight() + TEXT_SIZE) / 2 , mTextPaint); //绘制中奖文字 mCanvas.drawPath(mPath, mPaint); canvas.drawBitmap(mBitmap, 0, 0, null); //绘制刮奖图层 } } //解决自定义view 位置属性失效的问题 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int desiredWidth = WIDTH; int desiredHeight = HEIGHT; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height; //Measure Width if (widthMode == MeasureSpec.EXACTLY) { //Must be this size width = widthSize; } else if (widthMode == MeasureSpec.AT_MOST) { //Can't be bigger than... width = Math.min(desiredWidth, widthSize); } else { //Be whatever you want width = desiredWidth; } //Measure Height if (heightMode == MeasureSpec.EXACTLY) { //Must be this size height = heightSize; } else if (heightMode == MeasureSpec.AT_MOST) { //Can't be bigger than... height = Math.min(desiredHeight, heightSize); } else { //Be whatever you want height = desiredHeight; } //MUST CALL THIS setMeasuredDimension(width, height); } /** * 开启檫除功能 * * @param paintStrokeWidth 触点(橡皮)宽度 * @param touchTolerance 填充距离,值越小,越柔和。 */ public void beginScratch(final int paintStrokeWidth, float touchTolerance, String text) { mText = text; TOUCH_TOLERANCE = touchTolerance; // 设置画笔 mPaint = new Paint(); mPaint.setColor(Color.BLACK); // 此处不能为透明色 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圆角 mPaint.setStrokeCap(Paint.Cap.ROUND); // 后圆角 mPaint.setStrokeWidth(paintStrokeWidth); // 笔宽 mTextPaint = new Paint(); mTextPaint.setColor(Color.BLACK); mTextPaint.setStyle(Paint.Style.STROKE); mTextPaint.setTextSize(TEXT_SIZE); // 痕迹 mPath = new Path(); //Path主要用于绘制复杂的图形轮廓,比如折线,圆弧以及各种复杂图案 isDraw = true; } @Override public boolean onTouchEvent(MotionEvent event) { if (!isDraw) { return true; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 触点按下 touchDown(event.getX(), event.getY()); invalidate(); break; case MotionEvent.ACTION_MOVE: // 触点移动 touchMove(event.getX(), event.getY()); invalidate(); break; case MotionEvent.ACTION_UP: // 触点弹起 touchUp(event.getX(), event.getY()); invalidate(); break; default: break; } return true; } private void touchDown(float x, float y) { mPath.reset(); //reset()清除path设置的所有属性 mPath.moveTo(x, y); //moveTo方法将起始轮廓点移至x,y坐标点,默认情况为0,0点 mX = x; mY = y; } private void touchMove(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { //quadTo(float x1, float y1, float x2, float y2)方法:以当前路径结束点为开始点,(x1,y1)为控制点,(x2,y2)为结束点画一条二次贝塞尔曲线 mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; mY = y; } } private void touchUp(float x, float y) { mPath.lineTo(x, y); //lineTo(float x, float y)方法用于从当前轮廓点绘制一条线段到x,y点: mCanvas.drawPath(mPath, mPaint); mPath.reset(); } }
2.MainActivity.java:package com.example.administrator.scratchcards; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { //刮奖控件 private ScratchView mScratchView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mScratchView = (ScratchView) findViewById(R.id.view); mScratchView.beginScratch(40, 1f , "恭喜您!一等奖"); } }3.xml:
xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.scratchcards.MainActivity"> <TextView android:id="@+id/text" android:text="@string/hint" android:textSize="30dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="90dp" /> <Space android:id="@+id/space" android:layout_below="@+id/text" android:layout_width="match_parent" android:layout_height="20dp" /> <com.example.administrator.scratchcards.ScratchView android:id="@+id/view" android:layout_below="@+id/space" android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" /> RelativeLayout>tips:Android基础之Path类的使用:http://blog.csdn.net/mr_dsw/article/details/48931515