標籤:刮一刮 android canvas 橡皮檫 刮刮樂
前幾個月剛接觸Android的時候做了一個小項目,其中也用到了類似刮刮樂的效果,現在把代碼貼出來
首先要做一個類似橡皮擦的東西吧,然後才能把紙上的筆跡擦除
/** * FileName: SplashActivity.java * * @desc 橡皮擦功能,類似刮刮樂效果 * @author HTP * @Date 20140311 * @version 1.00 */public class Text_Rubbler extends TextView {private float TOUCH_TOLERANCE; // 填充距離,使線條更自然,柔和,值越小,越柔和。// private final int bgColor;// 位元影像private Bitmap mBitmap;// 畫布private Canvas mCanvas;// 畫筆private Paint mPaint;private Path mPath;private float mX, mY;private boolean isDraw = false;public Text_Rubbler(Context context) {/** * @param context 上下文 */super(context);}public Text_Rubbler(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// bgColor =// attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android",// "textColor", 0xFFFFFF);// System.out.println("Color:"+bgColor);}public Text_Rubbler(Context context, AttributeSet attrs) {super(context, attrs);// bgColor =// attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android",// "textColor", 0xFFFFFF);// System.out.println(bgColor);// System.out.println(attrs.getAttributeValue("http://schemas.android.com/apk/res/android",// "layout_width"));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (isDraw) {mCanvas.drawPath(mPath, mPaint);// mCanvas.drawPoint(mX, mY, mPaint);canvas.drawBitmap(mBitmap, 0, 0, null);}}/** * 開啟檫除功能 * * @param bgColor * 覆蓋的背景顏色 * @param paintStrokeWidth * 觸點(橡皮)寬度 * @param touchTolerance * 填充距離,值越小,越柔和。 */public void beginRubbler(final int bgColor, final int paintStrokeWidth,float touchTolerance) {TOUCH_TOLERANCE = touchTolerance;// 設定畫筆mPaint = new Paint();// mPaint.setAlpha(0);// 畫筆劃過的痕迹就變成透明色了mPaint.setColor(Color.BLACK); // 此處不能為透明色mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));// 或者// mPaint.setAlpha(0);// mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圓角mPaint.setStrokeCap(Paint.Cap.ROUND); // 後圓角mPaint.setStrokeWidth(paintStrokeWidth); // 筆寬// 痕迹mPath = new Path();;// 覆蓋// if (getLayoutParams().width == LayoutParams.FILL_PARENT) {//// }mBitmap = Bitmap.createBitmap(getLayoutParams().width,getLayoutParams().height, Config.ARGB_8888);mCanvas = new Canvas(mBitmap);mCanvas.drawColor(bgColor);isDraw = true;}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (!isDraw) {return true;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN: // 觸點按下// touchDown(event.getRawX(),event.getRawY());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();mPath.moveTo(x, y);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) {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);mCanvas.drawPath(mPath, mPaint);mPath.reset();}}
接下來就是使用橡皮檫擦除了
/** * FileName: RubblerAct.java * @Desc 該類通過調用Text_Rubbler這個類將在Activity上顯示一片刮一刮的地區,可以出發觸摸事件 * @author HTP * @Date 20140312 * @version 1.00 */public class RubblerAct extends Activity {// 刮開後文字顯示private TextView tv_rubbler;// 得到刮一刮的內容private Sentence mSentence;// 下一張private TextView tv_next;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// setContentView(new Rubble(this,"謝謝惠顧",new Rect(100, 200,// 300,250),2,1f,14));// /////////////////////////////////////////setContentView(R.layout.rubbler);// 設定的顏色必須要有透明度。((Text_Rubbler) findViewById(R.id.rubbler)).beginRubbler(0xFFFFFFFF, 20,1f);// 設定橡皮擦的寬度等mSentence = new Sentence();// 隨機初始化文字tv_rubbler = (TextView) findViewById(R.id.rubbler);String str = mSentence.getSentence();tv_rubbler.setText(str);tv_next = (TextView) findViewById(R.id.tv_next);// 點擊下一步tv_next.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString str = mSentence.getSentence();tv_rubbler.setText(str);((Text_Rubbler) findViewById(R.id.rubbler))// 初始化狀態.beginRubbler(0xFFFFFFFF, 20, 1f);}});}class Rubble extends View {private final int PAINT_STROKE_WIDTH;private final float TOUCH_TOLERANCE; // 填充距離,使線條更自然,柔和,值越小,越柔和。private final int TEXT_SIZE;private Bitmap mBitmap;// 畫布private Canvas mCanvas;// 畫筆private Paint mPaint;private Path mPath;private float mX, mY;private final int X, Y, W, H;private final Rect touchRect;public Rubble(Context context, String bgText, Rect rect,int paintStrokeWidth, float touchTolerance, int textSize) {super(context);setFocusable(true);touchRect = rect;W = rect.right - rect.left;H = rect.bottom - rect.top;X = rect.left;Y = rect.top;TEXT_SIZE = textSize;PAINT_STROKE_WIDTH = paintStrokeWidth;TOUCH_TOLERANCE = touchTolerance;setBackground(touchRect, bgText);initDrowTools();}private void setBackground(Rect rect, String bgText) {DisplayMetrics dm = new DisplayMetrics();dm = this.getResources().getDisplayMetrics();Bitmap bitmap = Bitmap.createBitmap(dm.widthPixels,dm.heightPixels, Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);Paint paint = new Paint();paint.setColor(0x88000000);// paint.setStyle(Style.STROKE);// paint.setTextAlign(Align.CENTER);paint.setTextSize(TEXT_SIZE);// paint.setTextScaleX(1.5f);canvas.drawColor(Color.WHITE);// 畫字的座標不好控制int x = rect.left+ (rect.right - rect.left - bgText.length() * TEXT_SIZE)/ 2;int y = rect.top + (rect.bottom - rect.top - TEXT_SIZE) / 2;// int y = 218+25;canvas.drawText(bgText, x, y, paint);Drawable drawable = new BitmapDrawable(bitmap);setBackgroundDrawable(drawable);}private void initDrowTools() {// 設定畫筆mPaint = new Paint();// mPaint.setAlpha(0);// 畫筆劃過的痕迹就變成透明色了mPaint.setColor(Color.BLACK); // 此處不能為透明色mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));// 或者// mPaint.setAlpha(0);// mPaint.setXfermode(new// PorterDuffXfermode(PorterDuff.Mode.DST_IN));mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圓角mPaint.setStrokeCap(Paint.Cap.ROUND); // 後圓角mPaint.setStrokeWidth(PAINT_STROKE_WIDTH); // 筆寬// 痕迹mPath = new Path();;// 覆蓋mBitmap = Bitmap.createBitmap(W, H, Config.ARGB_8888);mCanvas = new Canvas(mBitmap);mCanvas.drawColor(0x88000000);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mCanvas.drawPath(mPath, mPaint);// mCanvas.drawPoint(mX, mY, mPaint);canvas.drawBitmap(mBitmap, X, Y, null);}@Overridepublic boolean onTouchEvent(MotionEvent event) {System.out.print("X--" + event.getX());System.out.println("Y--" + event.getY());if (!touchRect.contains((int) event.getX(), (int) event.getY())) {return false;}switch (event.getAction()) {// 觸點按下case MotionEvent.ACTION_DOWN: {touchDown(event.getRawX(), event.getRawY());touchDown(event.getX() - touchRect.left, event.getY()- touchRect.top);invalidate();break;}case MotionEvent.ACTION_MOVE: // 觸點移動touchMove(event.getX() - touchRect.left, event.getY()- touchRect.top);invalidate();break;case MotionEvent.ACTION_UP: // 觸點彈起touchUp(event.getX() - touchRect.left, event.getY()- touchRect.top);invalidate();break;default:break;}return true;}private void touchDown(float x, float y) {mPath.reset();mPath.moveTo(x, y);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) {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);mCanvas.drawPath(mPath, mPaint);mPath.reset();}}/** * 鍵盤事件,當按下back鍵的時候詢問是否再按一次退出程式 */// 退出時間private long exitTime = 0;@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK&& event.getAction() == KeyEvent.ACTION_DOWN) {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(getApplicationContext(), "再按一次退出程式",Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {finish();System.exit(0);}return true;}return super.onKeyDown(keyCode, event);}}
實現效果如下:
Android實現刮刮樂效果