Below to write Introview's onmeasureheight:
private int measureheight (int measurespec) {int result = 0; int specmode = Measurespec.getmode (Measurespec); int specsize = measurespec.getsize (Measurespec); Paint paint = new paint (); Paint.settextsize (GetTextSize ()); Paint.setantialias (TRUE); Paint.setstyle (Style.fill); Displayheight =-paint.ascent () + paint.descent () + 2;//<span style= "font-family:arial, Helvetica, Sans-serif;" >-paint.ascent () is a portion of the font higher than Baseline paint.descent () for parts below baseline </span> measurelist (paint, titlelist, 0); if (Specmode = = measurespec.exactly) {result = Specsize; } else {if (Specmode = = measurespec.at_most) {result = Math.min ((int) displayheight, specsize); } else{result = (int) displayheight; }} return result; }private float measurelist (paint paint, arraylist<linkinfo> infolist, float StartX) {if (infolist = = NULL | | Infolist.size () = = 0) {displayheight = Startx;return StartX;} float x = Startx;int len = infolist.size ();//fontmetrics fontmetrics = Paint.getfontmetrics (); Float fontheight =-paint.as Cent () + paint.descent ()//fontmetrics.bottom-fontmetrics.top;for (int i = 0; i < len; i++) {LinkInfo info = infolist.g ET (i);//start calculating the click area of each link info.getrectflist (). Clear (), if (Info.isface ()) {//emoji bitmap facebmp = null;if (Mfacetype = = Msg_face_type) {facebmp = Messagefacemodel.getinstance (). Getfaceicon (Info.getcontent ());} if (facebmp! = null) {int xlen = Facebmp.getwidth () + 4;//emoticons left and right each empty two pixels if (x + Xlen >= displaywidth) {displayheight + = Fontheight;x = 0; } x + = Xlen;} Continue;} String strcontent = Info.getcontent (), strcontent = Strcontent.replaceall ("\ n", ""); float Xlen = Paint.measuretext ( strcontent);//The case where the newline is handled if (x + Xlen >= displaywidth) {float StartX = x;int lenstr = Strcontent.length (); for (int j = 0; j < Lenstr; J + +) {Float width = paint.measuretext (strcontent, J, j + 1), if (x + width >= displaywidth) {RECTF RECTF = new RECTF (); Rectf.set (StartX, Displayheight-fontheight, X, DISPL Ayheight); INFO.ADDRECTF (RECTF);d isplayheight + = Fontheight;x = width;//The starting offset of the x direction of the next line, and width is the offset of one character. So here RECTF only runs once startx = 0 at the time of the line break;} Else{x + = width;}} RECTF RECTF = new RECTF ();//Assuming a newline is startX to 0,x for the width of the next line Rectf.set (StartX, Displayheight-fontheight, X-startx, Displayheigh t); INFO.ADDRECTF (RECTF);} ELSE{RECTF RECTF = new RECTF () Rectf.set (x, displayheight-fontheight, x + Xlen, displayheight); INFO.ADDRECTF (RectF); x + = Xlen;}} return x;}
OnDraw:
@Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas); Try{if (titlelist = = NULL | | titlelist.size () = = 0) { return;} Curlen = 0; Paint paint = new paint ();p aint.settextsize (GetTextSize ());p Aint.setantialias (True);p Aint.setstyle (Style.fill); Float y =-paint.ascent ();//(fontmetrics.bottom-fontmetrics.ascent); y = drawlist (canvas, Paint, titlelist, y);} catch (Exception ex) {}}private float drawlist (canvas canvas, paint paint, arraylist<linkinfo> infolist, float Starty) {if (infolist = = NULL | | infolist.size () = = 0) {return starty;} Float y = starty;float fontheight =-paint.ascent () + paint.descent ();//fontmetrics.bottom-fontmetrics.ascent;int len = Infolist.size (); int color = Getcurrenttextcolor (); for (int i = 0; i < len; i++) {LinkInfo info = infolist.get (i); if (info). Isface ()) {//emoji typesetting bitmap facebmp = null;if (Mfacetype = = msg_face_type) {facebmp = Messagefacemodel.getinstance (). Getfaceicon (Info.getcontent ());} if (facebmp! = null) {int xlen = Facebmp.getwidth () + 4;//emoticons left and rightTwo pixels if (Curlen + xlen >= displaywidth) {y + = Fontheight; Curlen = 0; } canvas.drawbitmap (Facebmp, Curlen + 2, Y-fontheight + 4, paint); Curlen + = Xlen; } continue;} String strcontent = Info.getcontent (); if (Mfacetype = = Msg_face_type && strcontent.startswith ("\ n")) {y + = Fontheight;curlen = 0;} Strcontent = Strcontent.replaceall ("\ n", ""); if (Info.isemail () | | | Info.isphonenumber () | | Info.isweburl ()) && info.isselected () {PAINTSELECTRECTF (canvas, paint, info);} float Xlen = Paint.measuretext (strcontent); int starlen = 0;if (info.iscommonstring ()) {paint.setcolor (color);} Else{paint.setcolor (Getresources (). GetColor (R.drawable.blue1));} if (Curlen + Xlen + starlen >= displaywidth) {int lenstr = Strcontent.length (); for (int j = 0; J < Lenstr; J + +) {Float W Idth = Paint.measuretext (Strcontent, J, J + 1), if (Curlen + width >= displaywidth) {y + = Fontheight;curlen = 0;} Canvas.drawtext (Strcontent, J, j + 1, Curlen, y, paint); Curlen + = width;}} Else{canVas.drawtext (Strcontent, Curlen, y, paint); Curlen + = Xlen;}} return y;}
Ontouch event, can click the text inside the link (email,phone)
@Overridepublic boolean ontouchevent (Motionevent event) {super.ontouchevent (event); if (!this.isenabled () | | | Listener = = null) {return false;} if (event.getaction () = = motionevent.action_up) {float x = Event.getx (); Float y = Event.gety (); Boolean flag = Cancelcurinfo (x, y), if the coordinates of the IF (flag) {return false;//up are no longer in the link object recorded when down, the}if (Clicklink (titlelist, x, Y, motionevent.action_up) is returned directly {//log.i ("Curinfo", "action_up"); return true;}} else if (event.getaction () = = Motionevent.action_down) {float x = Event.getx (); Float y = Event.gety (); Boolean flag = Clickli NK (Titlelist, X, Y, Motionevent.action_down), if (flag) {//log.i ("Curinfo", "Action_down"); return true;}} Else{float x = Event.getx (); Float y = event.gety (); Cancelcurinfo (x, y);} return false; }private void PAINTSELECTRECTF (canvas canvas, paint paint, linkinfo info) {arraylist<rectf> rectlist = Info.getrectflist (); int len = Rectlist.size (); for (int i = 0; i < len; i++) {RECTF RECTF = rectlist.get (i);p Aint.setcolor (This.getcontext (). Getresources (). GetCOlor (R.DRAWABLE.GRAY3)); Canvas.drawrect (Rectf.left, Rectf.top-2, Rectf.right, rectf.bottom-2, Paint);}} /** x, y represents a point that is no longer in the current link object, clears the current link object's selected effect */private boolean cancelcurinfo (float x, float y) {if (Curinfo = = null) { return true;} if (!curinfo.contains (x, y)) {curinfo.setselected (false); This.invalidate (); curinfo = Null;return true;} return false;} Private Boolean Clicklink (arraylist<linkinfo> infolist, float x, float y, int action) {if (infolist = = null) {return FA LSE;} int len = Infolist.size (); for (int i = 0; i < len; i++) {LinkInfo info = infolist.get (i); if (info.iscommonstring ()) {Contin UE;} if (Info.contains (x, y)) {if (action = = Motionevent.action_down) {info.setselected (true); This.invalidate (); This.curinfo = info;} else if (action = = motionevent.action_up) {This.curinfo = null;info.setselected (false); this.invalidate (); Listener.onclick (info);} return true;}} return false;}
Listener:
Private Onclicklinklistener listener;public void Setonclicklinklistener (Onclicklinklistener Listener) {this. Listener = Listener;} Public interface onclicklinklistener{/** clicked on a link object in the dynamic */public abstract void OnClick (LinkInfo linkinfo);}
Code: http://download.csdn.net/detail/baidu_nod/7736733
Android assumes rewrite OnDraw implements a similar textview capable of displaying emoticons and linked controls (ii)