Android provides a smooth Effect
A small project was created just a few months ago when I first came into contact with Android, which also uses the effect similar to scratch. Now I have pasted the code
First, we need to make something similar to an eraser before we can erase the handwriting on the paper.
/*** FileName: SplashActivity. java ** @ desc eraser function, similar to the scratch effect * @ author HTP * @ Date 20140311 * @ version 1.00 */public class Text_Rubbler extends TextView {private float TOUCH_TOLERANCE; // fill distance, make the line more natural, soft, the smaller the value, the more soft. // Private final int bgColor; // Bitmap private Bitmap mBitmap; // Canvas private Canvas mCanvas; // brush 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_bler (context Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); // bgColor = // attrs. getAttributeI NtValue ("http://schemas.android.com/apk/res/android", // "textColor", 0 xFFFFFF); // 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", 0 xFFFFFF); // System. out. println (bgColor); // System. out. println (attrs. getAttributeValue ("http: // SC Hemas.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);}/*** enable the background color covered by the Division function ** @ param bgColor * @ param paintStrokeWidth * contact (rubber) width * @ param touchTolerance * fill distance. The smaller the value, the softer the value. */Public void beginRubbler (final int bgColor, final int paintStrokeWidth, float touchTolerance) {TOUCH_TOLERANCE = touchTolerance; // set the Paint brush mPaint = new (); // mPaint. setAlpha (0); // the paint brush trace turns transparent mPaint. setColor (Color. BLACK); // The mPaint cannot be transparent here. setXfermode (new porterduxfermode (PorterDuff. mode. DST_OUT); // or // mPaint. setAlpha (0); // mPaint. setXfermode (new porterduxfermode (PorterDuff. mode. DST_IN) ); MPaint. setAntiAlias (true); mPaint. setDither (true); mPaint. setStyle (Paint. style. STROKE); mPaint. setStrokeJoin (Paint. join. ROUND); // front rounded corner mPaint. setStrokeCap (Paint. cap. ROUND); // The mPaint rounded corner. setStrokeWidth (paintStrokeWidth); // stroke width // trace mPath = new Path (); // overwrite // 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: // contact Press // touchDown (event. getRawX (), event. getRawY (); touchDown (event. getX (), event. getY (); invalidate (); break; case MotionEvent. ACTION_MOVE: // move touchMove (event. getX (), event. getY (); invalidate (); break; case MotionEvent. ACTION_UP: // the 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 ();}}
The next step is to use the eraser to erase
/*** FileName: RubblerAct. the java * @ Desc class displays a scratch area on the Activity by calling Text_Rubbler, you can start to touch the event * @ author HTP * @ Date 20140312 * @ version 1.00 */public class RubblerAct extends Activity {// The private TextView TV _rubbler is displayed after the Activity is opened; // obtain the private Sentence mSentence. // The next private TextView TV _next; @ Overridepublic void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // setContentView (New Rubble (this, "Thank you for your patronage", new Rect (100,200, // 300,250), 2, 1f, 14 )); //////////////////////////////////////// /// setContentView (R. layout. rubbler); // The color must be transparent. (Text_Rubbler) findViewById (R. id. rubbler )). beginRubbler (0 xFFFFFFFF, 20, 1f); // set mSentence = new Sentence (); // initialize the text TV _rubbler = (TextView) findViewById (R. id. rubbler); String str = mSentence. getSentence (); TV _rubbler.setText (str); TV _next = (TextView) findViewById (R. id. TV _next); // click Next TV _next.setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {// TODO Auto-generat Ed method stubString str = mSentence. getSentence (); TV _rubbler.setText (str); (Text_Rubbler) findViewById (R. id. rubbler) // initialization status. beginRubbler (0 xFFFFFFFF, 20, 1f) ;}});} class Rubble extends View {private final int PAINT_STROKE_WIDTH; private final float TOUCH_TOLERANCE; // fill distance to make the line more natural, soft, the smaller the value, the more soft. Private final int TEXT_SIZE; private Bitmap mBitmap; // Canvas private Canvas mCanvas; // brush 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 = r Ect. bottom-rect. top; X = rect. left; Y = rect. top; TEXT_SIZE = textSize; margin = 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, C Onfig. 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); // it is difficult to control 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 () {// set the Paint brush mPaint = new Paint (); // mPaint. setAlpha (0); // the paint brush trace turns transparent mPaint. setColor (Color. BLACK); // The mPaint cannot be transparent here. setXfermode (new porterduxfermode (PorterDuff. mode. DST_OUT); // or // mPaint. setAlpha (0); // mPaint. setXfermode (New // porterduxfermode (PorterDuff. mode. DST_IN); mPaint. setAntiAlias (true); mPaint. setDither (true); mPaint. setStyle (Paint. style. STROKE); mPaint. setStrokeJoin (Paint. join. ROUND); // front rounded corner mPaint. setStrokeCap (Paint. cap. ROUND); // The mPaint rounded corner. setStrokeWidth (PAINT_STROKE_WIDTH); // stroke width // trace mPath = new Path (); // overwrite mBitmap = Bitmap. createBitmap (W, H, Config. ARGB_8888); mCanvas = new Canvas (mBitmap); mCanvas. drawC Olor (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 () {// contact press case MotionEvent. ACTION_DOWN: {touchDown (event. getRawX (), event. getRawY (); touchDown (event. getX ()-touchRect. left, event. getY ()-touchRect. top); invalidate (); break;} case MotionEvent. ACTION_MOVE: // move touchMove (event. getX ()-touchRect. left, event. getY ()-touchRect. top); invalidate (); break; case MotionEvent. ACTION_UP: // the 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 () ;}/ *** keyboard event. When the back key is pressed, ask whether to exit the program again. * // The Exit Time is 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 (), "exit the program again", Toast. LENGTH_SHORT ). show (); exitTime = System. currentTimeMillis ();} else {finish (); System. exit (0);} return true;} return super. onKeyDown (keyCode, event );}}
The implementation result is as follows: