Presumably everyone has used QQ whiteboard function, there are two main, one is the graffiti function, in fact, similar to the previous section of the artboard function, and the other is handwritten, that notepad how can not this function, today to add handwriting for our Notepad.
First, look at the effect:
See, is not the heartbeat? Then hurry up to do it, in fact, the handwriting function is not difficult to achieve, is generally full-screen writing, timed to send handle messages, update activity.
The main steps to implement handwriting:
1. Customize two view, one is Touchview, used to draw on it, and the other is EditText, used to display handwritten words in it, and two custom view is overlapped by framelayout frame layout to realize full-screen handwriting.
2 write in Touchview and intercept the words in the canvas to save bitmap.
3. Set the timer to update the interface with handle.
Here are the details of the implementation:
1. Hand-written interface design:
As shown in the previous section of the artboard interface, the bottom of the Options menu bar, there are 5 options, namely, adjust the brush size, brush color, undo, redo, and empty, for these functions, the following sections are implemented.
Layout file Activity_handwrite.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 "android:background=" @android: Co Lor/white "> <framelayout android:layout_width=" fill_parent "android:layout_height=" Wrap_content "android:id= "@+id/finger_layout" > <com.example.notes.lineedittext android:id= "@+id/et_handwrite" Android:layout_width= "Match_parent" android:layout_height= "match_parent" android:scrollbars= "vertical" Android:fadingedge= "vertical" android:inputtype= "Textmultiline" android:gravity= "Top" Android:tex Tsize= "20SP" android:layout_margin= "5DP" android:focusable= "true" android:linespacingextra= "10DP" Android:textcolor= "#00000000" android:background= "#00000000"/> <com.example.not Es. TouchView android:id= "@+id/touch_view "android:layout_width=" fill_parent "android:layout_height=" Wrap_content "android:backg Round= "@android: Color/transparent" > </com.example.notes.TouchView> </FrameLayout> <imag Eview android:layout_width= "match_parent" android:layout_height= "wrap_content" android:src= "@drawable/line "Android:layout_above=" @+id/paintbottommenu "/> <gridview android:id=" @+id/paintbottommenu " Android:layout_width= "Match_parent" android:layout_height= "45DP" android:numcolumns= "Auto_fit" an droid:background= "@drawable/navigationbar_bg" android:horizontalspacing= "10DP" Android:layout_alignparentbotto M= "true" ></GridView></RelativeLayout>
As you can see, there are two custom view, and they overlap by framelayout.
First look at Com.example.notes.LineEditText, which is actually the same as adding a note in the interface, is to customize the EditText, and the word below the line to draw.
Lineedittext.java
public class Lineedittext extends EditText {private Rect mrect;private Paint mpaint;public lineedittext (context context, A Ttributeset attrs) {//TODO auto-generated constructor Stubsuper (context,attrs); mrect = new Rect (); mpaint = new Paint (); MP Aint.setcolor (Color.gray);} @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);//Get EditText total number of rows int linecount = Getlinecount (); Rect r = mrect; Paint p = mpaint;//Sets the format for each line for (int i = 0; i < linecount;i++) {//Gets the datum y-coordinate of each row, and writes the bounds value of each line to r int baseline = Getlinebounds (i , r);//Set the text of each line underlined Canvas.drawline (R.left, baseline+20, R.right, baseline+20, p);}}
Another is the com.example.notes.TouchView, the implementation of the drawing, and the function of the regular update interface, the specific look at the code
Touchview.java
public class TouchView extends View {private Bitmap mbitmap,mybitmap;private Canvas mcanvas;private Path Mpath;priva Te paint mbitmappaint;private paint mpaint;private Handler bitmaphandler; Getcutbitmaplocation getcutbitmaplocation;private Timer timer;displaymetrics dm;private int w,h;public TouchView ( Context context) {super (context); DM = new Displaymetrics ();((Activity) context). Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM); W = dm.widthpixels; h = dm.heightpixels;initpaint (); } public TouchView (context context, AttributeSet Attrs) {super (context,attrs);d m = new Displaymetrics ();((Activity) con Text). Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM); w = dm.widthpixels; h = Dm.heightpixels;initpaint ();} Set handlerpublic void SetHandler (Handler mbitmaphandler) {bitmaphandler = Mbitmaphandler;} Initialize brush, canvas private void Initpaint () {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 (15); Getcutbitmaplocation = new Getcutbitmaplocation (); Canvas Size Mbitmap = Bitmap.createbitmap (W, H, Bitmap.Config.ARGB_8888); Mcanvas = new Canvas (MBITMAP); All Mcanvas paintings are preserved in the Mbitmap Mcanvas.drawcolor (color.transparent); MPath = new Path (); Mbitmappaint = new Paint (Paint.dither_flag); Timer = new timer (true);} /** * Processing screen display */handler Handler = new Handler () {public void Handlemessage (Message msg) {switch (msg.what) {case 1:mybitmap = Getcutbitmap (Mbitmap); Message message = new Message (); message.what=1; Bundle bundle = new bundle (); Bundle.putparcelable ("Bitmap", Mybitmap); Message.setdata (bundle); bitmaphandler.sendmessage (message); Refershbitmap (); break;} Super.handlemessage (msg);}};/ * * Send message to handler update activity */timertaSK task = new TimerTask () {public void run () {Message message = new Message (); message.what=1; LOG.I ("Thread", "Come"); handler.sendmessage (message);}};/ /Cut the words in the canvas and return to the public Bitmap Getcutbitmap (Bitmap mbitmap) {//Get to write around the position and extend outward 10pxfloat cutleft = Getcutbitmaplocation.getcutleft ()-10;float cuttop = Getcutbitmaplocation.getcuttop ()-10;float cutRight = Getcutbitmaplocation.getcutright () + 10;float Cutbottom = Getcutbitmaplocation.getcutbottom () + 10;cutLeft = (0 > CutL Eft? 0:cutleft) Cuttop = (0 > Cuttop 0:cuttop); cutright = (Mbitmap.getwidth () < cutright? Mbitmap.getwidth (): Cut right); Cutbottom = (Mbitmap.getheight () < Cutbottom mbitmap.getheight (): Cutbottom);//Get handwritten height and width float cutwidth = c Utright-cutleft;float cutheight = cutbottom-cuttop; Bitmap Cutbitmap = Bitmap.createbitmap (Mbitmap, (int) cutleft, (int) cuttop, (int) cutwidth, (int) cutheight); if (Mybitmap !=null) {mybitmap.recycle (); mybitmap= null;} return cutbitmap;} Refresh Canvas private void Refershbitmap () {initpaint (); INvalidate (); if (task! = null) Task.cancel ();} @Override protected void OnDraw (canvas canvas) {canvas.drawbitmap (mbitmap, 0, 0, mbitmappaint); Displays the old canvas Canvas.drawpath (MPath, mpaint); Draw the last path} private float MX, MY; Private static final float touch_tolerance = 4; private void Touch_start (float x, float y) {mpath.reset ();//empty path Mpath.moveto (x, y); MX = x; MY = y; if (task! = null) task.cancel ();//Cancel before task = new TimerTask () {@Overridepublic void run () {Message message = new Message (); message.what=1; LOG.I ("Thread", "Come"); handler.sendmessage (message);}}; Getcutbitmaplocation.setcutleftandright (mx,my); }//hand movement when 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; if (task! = null) task.cancel ();//Cancel task before tasks = new TimerTask () {@Override public void Ru N () {Message message = new Message (); Message.what=1; LOG.I ("Thread", "Come"); Handler.sendmessage (message); } }; Getcutbitmaplocation.setcutleftandright (mx,my); }}//hands raised when private void Touch_up () {//mpath.lineto (MX, MY); Mcanvas.drawpath (MPath, mpaint); Mpath.reset (); if (timer!=null) {if (task!=null) {task.cancel (); task = new TimerTask () {public void run () {Message message = new Message ( ); message.what = 1;handler.sendmessage (message);}}; Timer.schedule (Task, 1000, 1000);//2,200 seconds after sending a message to handler update Activity}}else {timer = new timer (true); Timer.schedule (Task, 1000, 1000);//2,200 seconds after sending message to handler update activity}}//Processing interface Event @Override public boolean ontouchevent (Motionevent event) {float x = Event.getx (); Float y = event.gety (); Switch (event.getaction ()) {case MotionEvent.ACTION_DOWN:touch_start (x, y); Invalidate (); Refresh break; Case MotionEvent.ACTION_MOVE:touch_move (x, y); Invalidate (); Break Case MotionEvent.ACTION_UP:touch_up (); Invalidate (); Break } return true; }}
The difficulty in this is to use TimerTask and handle to update the interface display, you need to ontouchevent in three events to send a message through the handle to update the display interface.
The next step is to get the word drawn through handle in the activity and add it to the EditText.
About configuring the bottom menu, as well as the top title bar, here no longer repeat, directly how to draw the word to get, and add in EditText:
Get the bitmap of the drawing font
Processing interface Handler Handler = new Handler () {@Overridepublic void Handlemessage (Message msg) {super.handlemessage (msg); Bundle bundle = new bundle (); bundle = Msg.getdata (); Bitmap Mybitmap = bundle.getparcelable ("Bitmap"); Inserttoedittext (Mybitmap);} };
Where Mybitmap is the handwritten word obtained, saved in bitmap, Inserttoedittext (Mybitmap); is to add the picture in EditText, as follows:
Et_handwrite = (lineedittext) Findviewbyid (r.id.et_handwrite);
Insert hand writing into EditText private void Inserttoedittext (Bitmap mbitmap) { int imgwidth = Mbitmap.getwidth (); int ImgHeight = Mbitmap.getheight ();//scale float Scalew = (float) (80f/imgwidth); float Scaleh = (float) (100f/imgheight); Matrix MX = new Matrix ();//Scale the original image Mx.postscale (Scalew, Scaleh); mbitmap = Bitmap.createbitmap (mbitmap, 0, 0, imgwidth, im Gheight, MX, true);//insert handwritten words into edittext spannablestring ss = new Spannablestring ("1"); Imagespan span = new Imagespan ( Mbitmap, Imagespan.align_bottom); Ss.setspan (span, 0, 1, spannable.span_inclusive_exclusive); Et_handwrite.append (ss ); }
In this way, the function of handwriting is realized, and the following section realizes the function of undo, redo and emptying of handwritten words.
Notepad for Android project (6)-----Add handwriting