Notepad for Android project (8)-----The undo, redo, and erase of artboard functions

Source: Internet
Author: User
Tags clear screen save file

The previous section discussed the deletion, recovery, and emptying features in handwriting, so how can the artboard be a function of undo, redo, and erase, which is implemented today.

Finally will do GIF map, see the following dynamic diagram, is not and QQ whiteboard function very much like.

Previously, it was simple to draw on the artboard, so the custom view was written directly in the activity, which was separated by the ability to undo, redo, and empty. A separate Java file, Paintview.java, implements the basic operation of the artboard in this custom view.

Since the custom view is separated separately, it needs to be changed to the activity's layout file:

Activity_paint.xml

< ? xml version= "1.0" encoding= "Utf-8"? ><relativelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "Android:layout_width=" Match_parent "android:layout_height=" match_parent "> <com.example.not Es. Paintview android:id= "@+id/paint_layout" android:layout_width= "match_parent" android:layout_height= "MATC        H_parent "></com.example.notes.PaintView> <gridview android:id=" @+id/paintbottommenu " Android:layout_width= "Match_parent" android:layout_height= "45DP" android:numcolumns= "Auto_fit" Android : background= "@drawable/navigationbar_bg" android:horizontalspacing= "10DP" android:layout_alignparentbottom= "tr UE "></GRIDVIEW></RELATIVELAYOUT> 

Where Com.example.notes.PaintView is a custom view

This SectionTo implementation has undo, redo, empty and save, and the following are the main ideas for three operations:

To implement undo and redo, there is a premise to put the path of each drawing into the stack, which is stored in the list.

1. Undo function:

premise: The path of each draw is stored in the list, which is deposited into the Savepath

Steps:

1) Empty the canvas, where you can use the initialized operation
2) Save the last path in Savepath to another list, that is, Deletepath (for recovery), and remove this path from Savepath

3) Remove all the paths from the Savepath and redraw them on the canvas

2. Recovery function:

premise: The path of each revocation is deposited into the list, which is deposited into the Deletepath

Steps:

1) Remove the last path in the Deletepath and save it to the Savepath

2) Redraw the removed path onto the canvas

3) Remove the last path from Deletepath

3. Clear function:

1) Empty the canvas directly and invoke the initialization of the canvas

2) Empty the list of two saved paths

 

4. Save function:

1) Get the current time, take the time as the drawing file name (avoid overwriting)

2) because the canvas is built on the bitmap, save the drawn bitmap on the SD card

3) Return the path to the drawing file

The above operation is not difficult, the focus is to save each path drawn on the canvas in the list, it is important to note that when you press, you should recreate the path, when lifted, the path created when the press should be set to NULL, so that each path can be saved.

          below directly to the code that defines the view, there are also comments:

Package Com.example.notes;import Java.io.file;import Java.io.filenotfoundexception;import Java.io.FileOutputStream ; Import Java.io.ioexception;import java.text.simpledateformat;import java.util.arraylist;import java.util.Date; Import Java.util.iterator;import Android.app.activity;import Android.content.context;import Android.graphics.bitmap;import Android.graphics.canvas;import Android.graphics.color;import Android.graphics.paint;import Android.graphics.path;import Android.util.attributeset;import Android.util.displaymetrics;import android.view.motionevent;import android.view.view;/**** @category: View for Graffiti, Undo and Redo Functions * @author: jesson20121020* @link: blog.csdn.net/jesson20121020* @date: 2014.9.19**/public class Paintview Extends View {private Canvas mcanvas;private Path mpath;private Paint mbitmappaint;private Bitmap mbitmap;private    Paint Mpaint;    Private arraylist<drawpath> Savepath;    Private arraylist<drawpath> Deletepath;        Private DrawPath DP; Private FloAt MX, MY;                Private static final float touch_tolerance = 4;        private int bitmapwidth;                private int bitmapheight;            Public Paintview (Context c) {super (c);    Get the screen resolution displaymetrics DM = new Displaymetrics ();        (Activity) c). Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM);    Bitmapwidth = Dm.widthpixels;                Bitmapheight = dm.heightpixels-2 * 45;            Initcanvas ();            Savepath = new arraylist<drawpath> ();                    Deletepath = new arraylist<drawpath> ();            } public Paintview (Context C, AttributeSet attrs) {super (c,attrs);    Get the screen resolution displaymetrics DM = new Displaymetrics ();                (Activity) c). Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM);    Bitmapwidth = Dm.widthpixels;        Bitmapheight = dm.heightpixels-2 * 45;            Initcanvas ();        Savepath = new arraylist<drawpath> ();    Deletepath = new arraylist<drawpath> ();            }//Initialize canvas public void Initcanvas () {mpaint = new Paint ();            Mpaint.setantialias (TRUE);            Mpaint.setdither (TRUE);            Mpaint.setcolor (0XFF00FF00);            Mpaint.setstyle (Paint.Style.STROKE);            Mpaint.setstrokejoin (Paint.Join.ROUND);            Mpaint.setstrokecap (Paint.Cap.ROUND);                          Mpaint.setstrokewidth (10);                                           Mbitmappaint = new Paint (Paint.dither_flag);            Canvas Size Mbitmap = Bitmap.createbitmap (Bitmapwidth, Bitmapheight, Bitmap.Config.RGB_565);  Mcanvas = new Canvas (MBITMAP);            All Mcanvas paintings are preserved in the Mbitmap Mcanvas.drawcolor (color.white);            MPath = new Path ();                    Mbitmappaint = new Paint (Paint.dither_flag);               } @Override protected void OnDraw (canvas canvas) {        Canvas.drawbitmap (mbitmap, 0, 0, mbitmappaint);    Displays the old canvas if (mPath! = null) {//real-time display Canvas.drawpath (MPath, mpaint);        }}//Path object class drawpath{path path;        Paint paint;     The core idea of/** * undo is to empty the canvas, * Remove the last path from the saved path, and re-draw it onto the canvas.        */public void undo () {System.out.println (savepath.size () + "--------------");                    if (Savepath! = null && savepath.size () > 0) {//Call the Initialize Canvas function to empty the canvas Initcanvas ();            Delete the last element in the path save list and save it in the path delete list DrawPath DrawPath = Savepath.get (Savepath.size ()-1);            Deletepath.add (DrawPath);                        Savepath.remove (Savepath.size ()-1); Redraws the path in the path save list on the canvas iterator<drawpath> iter = Savepath.iterator ();//Duplicate Save while (Iter.hasnext ()) {D    Rawpath DP = Iter.next ();        Mcanvas.drawpath (Dp.path, dp.paint); } invalidate ();//Refresh       The core idea of/** recovery is to save the undo path to a different list (stack), and then remove the topmost object from the list of redo, * draw it on the canvas * */ public void Redo () {if (deletepath.size () > 0) {//will delete the last of the path list, that is, the top-most path out (stack), and add the path to the Save list DrawPath        DP = Deletepath.get (Deletepath.size ()-1);        Savepath.add (DP);        Redraws the removed path on the canvas Mcanvas.drawpath (Dp.path, dp.paint);        Remove the path from the list of deleted paths Deletepath.remove (Deletepath.size ()-1);        Invalidate ();        The main idea of emptying is to initialize the canvas * Two list of saved paths empty * */public void Removeallpaint () {    Call the Initialize Canvas function to empty the canvas Initcanvas ();    Invalidate ();//Refresh savepath.clear ();        Deletepath.clear (); }/* * Save the drawing * Returns the path to the plot file * */Public String Savebitmap () {//Gets the current time of the system and              The time as filename simpledateformat formatter = new SimpleDateFormat ("Yyyymmddhhmmss"); Date curdate = new Date (System.currenttimemillis());//Gets the current time of the String str = Formatter.format (curdate);            String Paintpath = "";            str = str + "Paint.png";            File dir = new file ("/sdcard/notes/");            File File = new file ("/sdcard/notes/", str);             if (!dir.exists ()) {Dir.mkdir ();            } else{if (File.exists ()) {file.delete ();    }} try {FileOutputStream out = new FileOutputStream (file);     Mbitmap.compress (Bitmap.CompressFormat.PNG, N, out);     Out.flush ();     Out.close ();            Save drawing file path Paintpath = "/sdcard/notes/" + str;    } catch (FileNotFoundException e) {//TODO auto-generated catch block E.printstacktrace ();    } catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();      } return Paintpath; } private void Touch_start (float x, float y) {mpath.reset ();//Empty path MPath.moveto (x, y);            MX = x;        MY = y;            } private void Touch_move (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, y);                Mpath.quadto (MX, my, (x + MX)/2, (y + MY)/2);//The source code is written like this, but I don't understand why?                MX = x;            MY = y;            }} private void Touch_up () {Mpath.lineto (MX, MY);            Mcanvas.drawpath (MPath, mpaint);            Savepath.add (DP);                    MPath = null;            } @Override public boolean ontouchevent (Motionevent event) {float x = Event.getx ();                        Float y = event.gety (); Switch (event.getaction ()) {Case MotionEvent.ACTION_DOWN:mPath = n                    EW Path (); DP = new DrawPath ();                    Dp.path = MPath;                                        Dp.paint = Mpaint;                    Touch_start (x, y); Invalidate ();                Clear screen break;                    Case MotionEvent.ACTION_MOVE:touch_move (x, y);                    Invalidate ();                Break                    Case MotionEvent.ACTION_UP:touch_up ();                    Invalidate ();            Break        } return true; }  }

The next step is to invoke these action methods in the custom view in the activity:

Private Paintview Paintview;         Private GridView Paint_bottommenu;
Paint_bottommenu = (GridView) Findviewbyid (r.id.paintbottommenu);p Aint_bottommenu.setonitemclicklistener (new Menuclickevent ());p Aintview = (paintview) Findviewbyid (r.id.paint_layout);
          Set menu item Listener   class Menuclickevent implements onitemclicklistener{  @Override public  void Onitemclick ( Adapterview<?> Parent, view view, int position,  long id) {  Intent Intent;  Switch (position) {  //brush size case  0: Break    ;  Color Case  1: Break    ;  Revocation Case  2:  Paintview.undo ();  break;  Recovery Case   3:  Paintview.redo ();  break;  Empty Case  4:  paintview.removeallpaint ();  break;    Default: Break;}}}   

This is because there is a save file, so you have to read and write the SD card permissions:

<uses-permission android:name= "Android.permission.WRITE_EXTERNAL_STORAGE"/>

At this point, has completed the removal of the artboard, restore, empty, save the function, as for the other functions, slowly realized later.




Notepad for Android project (8)-----The undo, redo, and erase of artboard functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.