Record the development of the eraser function.
Explain the principle:
The eraser function uses a property of the paint class:
Paint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.DST_IN));
The meaning of this code is:
Draw the target image only where the source image and the target image intersect
It doesn't matter, first draw the line with a paint, then use another paint as the eraser and set the property of the code above, then it becomes the eraser.
Oh, my God, what the hell am I talking about?
Let's look at the code.
Look at the code in seconds to understand ...
Package Com.example.testwhatever;import Android.app.activity;import Android.content.context;import Android.graphics.bitmap;import Android.graphics.bitmap.config;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.os.Bundle;import Android.util.displaymetrics;import Android.view.motionevent;import Android.view.view;import Android.view.view.onclicklistener;import Android.view.viewgroup.layoutparams;import Android.widget.Button;import Android.widget.linearlayout;public class Canvasactivity extends Activity {private int screen_w;private int screen_h; private int Pen = 1;private int Eraser = 2; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (sav Edinstancestate); LinearLayout layout = new LinearLayout (this); Layout.setorientation (linearlayout.vertical); Layoutparams params = new Layoutparams (layoutparams.wrap_coNtent,layoutparams.wrap_content); Button paint = New button (this);p aint.settext ("brush"); Layout.addview (paint, params); Button eraser = New button (this), Eraser.settext ("Eraser"), Layout.addview (eraser, params), final MyView MyView = new MyView ( this); Layout.addview (MyView); Setcontentview (layout);p Aint.setonclicklistener (new Onclicklistener () {@ overridepublic void OnClick (View v) {myview.setmode (Pen);}}); Eraser.setonclicklistener (New Onclicklistener () {@Overridepublic void OnClick (View v) {myview.setmode (eraser);}});} MyView is the custom artboard class MyView extends View {private int mmode = 1;private Bitmap mbitmap;private Canvas mcanvas;private Pai NT Meraserpaint;private Paint mpaint;private Path mpath;private float MX, my;private static final float touch_tolerance = 4;public MyView (Context context) {super (context); setfocusable (true); Setscreenwh (); Initpaint ();} private void Setscreenwh () {displaymetrics dm = new Displaymetrics ();d m = this.getresources (). Getdisplaymetrics (); int ScreenWidth = Dm.widthpixelS;int screenheight = dm.heightpixels; Screen_w = ScreenWidth; Screen_h = ScreenHeight;} Sets whether the drawing mode is "brush" or "eraser" public void SetMode (int mode) {This.mmode = mode;} private void Initpaint () {//Brush mpaint = new Paint (); Mpaint.setantialias (true); Mpaint.setstyle (Paint.Style.STROKE); Mpaint.setstrokecap (Paint.Cap.ROUND); Mpaint.setstrokejoin (Paint.Join.ROUND); Mpaint.setcolor (Color.Black); Mpaint.setstrokewidth (10);//Eraser Meraserpaint = new Paint (); Meraserpaint.setalpha (0);//This property is set to Paint as the weight of the eraser weight//This is the focus// The following code is the focus of the eraser setting Meraserpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.DST_IN));// The above code is the focus of the eraser setting (important thing is not to say three times) Meraserpaint.setantialias (true); Meraserpaint.setdither (true); Meraserpaint.setstyle (Paint.Style.STROKE); Meraserpaint.setstrokejoin (Paint.Join.ROUND); Meraserpaint.setstrokewidth (+); MPath = new Path (); mbitmap = Bitmap.createbitmap (Screen_w, Screen_h, config.argb_8888 ); Mcanvas = new Canvas (MBITMAP);} @Overrideprotected void OnDraw (canvas canvas) {if (Mbitmap! = null) {Canvas.drawbitmap (mbitmap, 0, 0, mpaint);} Super.ondraw (canvas);} private void Touch_start (float x, float y) {mpath.reset (); Mpath.moveto (x, y), MX = X;my = y;//If the brush mode is drawn with the Mpaint brush if (MM Ode = = Pen) {Mcanvas.drawpath (MPath, mpaint);} If it is "eraser" mode, use Meraserpaint brush to draw if (Mmode = = Eraser) {Mcanvas.drawpath (MPath, Meraserpaint);}} private void Touch_move (float x, float y) {float dx = math.abs (x-mx); float dy = Math.Abs (y-my); if (DX >= touch_tole RANCE | | Dy >= touch_tolerance) {mpath.quadto (MX, my, (x + MX)/2, (y + MY)/2), MX = X;my = y;if (Mmode = = Pen) {MCANVAS.DRAWP Ath (MPath, mpaint);} if (Mmode = = Eraser) {Mcanvas.drawpath (MPath, Meraserpaint);}}} private void Touch_up () {Mpath.lineto (MX, MY), if (Mmode = = Pen) {Mcanvas.drawpath (MPath, mpaint);} if (Mmode = = Eraser) {Mcanvas.drawpath (MPath, Meraserpaint);}} @Overridepublic boolean ontouchevent (Motionevent event) {float x = Event.getx (); Float y = event.gety (); switch (Event.geta Ction ()) {case MotionEvent.ACTION_DOWN:touch_start (x, y); invalidate (); Break;case MotiOnEvent.ACTION_MOVE:touch_move (x, y); invalidate (); Break;case MotionEvent.ACTION_UP:touch_up (); invalidate (); break ;} return true;}}}
And then it's Jiangzi:
In fact, that is, the paint of the brush and the eraser of the paint two images intersect, and then will draw the intersection of the area, the intersection of the area is not drawn to white, but transparent. This is because the eraser's paint sets that very important attribute: Porterduff.mode. dst_in
In order to prove that the intersection area is really transparent, not white, set a background map for MyView, and if it is white, the background map will be painted white. If it is transparent, the background map will not be affected.
Add a code in the constructor of MyView in the preceding code: Setbackgroundresource (R.drawable.picture);
The result diagram is then run Jiangzi:
So this is why it is recommended to set the paint for this porterduff.mode when developing the eraser function. The dst_in property, instead of simply drawing white.
There are also many models for Porterduff.mode:
Android.graphics.PorterDuff.Mode. SRC: Drawing only source images
Android.graphics.PorterDuff.Mode. DST: Draw only the target image
Android.graphics.PorterDuff.Mode. dst_over: Draws the target image at the top of the source image
Android.graphics.PorterDuff.Mode. dst_in: Draws the target image only where the source image and the target image intersect
Android.graphics.PorterDuff.Mode. dst_out: Draws the target image only where the source image and the target image do not intersect
Android.graphics.PorterDuff.Mode. dst_atop: Draws the target image where the source and destination images intersect, drawing the source image where it does not intersect
Android.graphics.PorterDuff.Mode. src_over: Draws the source image at the top of the target image
Android.graphics.PorterDuff.Mode. src_in: Draws the source image only where the source and destination images intersect
Android.graphics.PorterDuff.Mode. src_out: Draws the source image only where the source and destination images do not intersect
Android.graphics.PorterDuff.Mode. src_atop: Draws the source image where the source and destination images intersect, and draws the target image where it does not intersect
Android.graphics.PorterDuff.Mode. XOR: Draw them anywhere outside of the source image and target image, and do not draw any content where they do not overlap
Android.graphics.PorterDuff.Mode. lighten: Obtains the brightest pixel in two images in each position and displays
Android.graphics.PorterDuff.Mode. Darken: Obtains the darkest pixel of two images in each position and displays
Android.graphics.PorterDuff.Mode. MULTIPLY: Multiplies two pixels per location by 255, and then uses that value to create a new pixel to display. Result color = top Color * Bottom Color/255
Android.graphics.PorterDuff.Mode. screen: Invert each color, perform the same action (multiply them by 255), and then invert again. Result Color =255-(((255-top color) * (255-bottom color))/255)
Each mode can be set to play, to see what the effect of each property ~ ~ ~ I will not play such a boring thing anyway. I'm lazy. ~~~o (∩_∩) o~~
Development of eraser function for Android artboard