TextView in Android is a UI class that displays text, in real-world requirements, the text has a variety of styles, TextView itself does not have the properties to set the implementation, we can provide through the Androidspannablestring class encapsulation. Android provides a lot of span classes to implement styles that are inherited fromCharacterstyle class. in the previous blog detailed introduction of how to use a variety of span classes, this blog mainly by looking at the source code, to analyze the working principle of span, the internal class structure, inheritance structure, so that we can customize a span to use.
To analyze the principle of span, we need to understand textview of the approximate drawing process, a textview similar is very complex, 1.1 point to see the source code, look for the order.
First, in the Charcaterstyle class, you have Public Abstract voidupdatedrawstate (textpaint tp);method, Textpaint is a brush, I personally think that Textpaint has no effect, directly as paint to see on the line. Since updatedrawstate needs to paint, then you need to call this method in the TextView OnDraw, which is passed to the painting text in the OnDraw method, this method can work, Then we look at TextView in the OnDraw method, the code is too much, I only paste the key code. in TextView's OnDraw method, only the following method is called to the brush. Path Highlight = Getupdatedhighlightpath (); if (meditor ! = null) { meditoronDraw (canvas, layout, highlight, mhighlightpaint, cursoroffsetvertical);} Else {Layout.draw (canvas, highlight, mhighlightpaint, cursoroffsetvertical); } if (mmarquee ! = null && mmarquee. Shoulddrawghost ()) {canvas.translate ((int) mmarquee. Getghostoffset (), 0.0f);Layout.draw (canvas, highlight, mhighlightpaint, cursoroffsetvertical); }
There are two classes that can be found here: Editor and Layout,textview OnDraw are plotted in these two classes, and continue to see the effects of these two classes respectively. 1.Editor: No source code has been found. Put down the shelving and then say 2. Layout: You can see that layout has three sub-classes, Boringlayout,Dynamiclayout,Staticlayout, these three classes are a package of functions, and the main implementation is in layout,Let's take a look at the code in layout: Public voidDraw (Canvas canvas, PathHighlight, Paint Highlightpaint, int cursoroffsetvertical) { final long linerange = Getlinerangefordraw (canvas); int firstline = Textutils.unpackrangestartfromlong (linerange); int lastline = Textutils.unpackrangeendfromlong (linerange); If (lastline < 0) return;drawbackground (canvas, highlight, Highlightpaint, Cursoroffsetvertical,Firstline, lastline);drawText (Canvas, Firstline, lastline); }Drawbackground Drawing Background
DrawText Drawing Text
The key code has been found. Then look at the source code in DrawText: If (directions = = Dirs_all_left_to_right &&! Mspannedtext &&!hastaboremoji) { // XXX: Assumes there ' s nothing additional Canvas.drawtext (buf, start, end, X, Lbaseline, paint);} Else {tl.set (Paint, buf, start, end, dir, directions, Hastaboremoji, tabStops);Tl.draw (canvas, X, Ltop, Lbaseline, lbottom); }
can see is a judgment condition, directly can draw text, but we have not found about the span of code ah, do not, do not worry, there are tl.draw. See Source:
Replacementspan replacement = null;
for (int j = 0; J < Mmetricaffectingspanspanset.numberofspans; J + +) { //Both intervals [Spanstarts. Spanends] and [Mstart + I.. Mstart + Mlimit] is not Empty by construction. This special case in Getspans () explains the >= & <= tests & nbsp; if ((Mmetricaffectingspanspanset.spanstarts[j] >= MStart + mlimit) | | (Mmetricaffectingspanspanset.spanends[j] <= Mstart + i)) continue; Metricaffectingspan span = Mmetricaffectingspanspanset.spans[j]; if (span instanceof Replacementspan) { replacement = (Replacementspan) span; } else { //We might have a replacement that uses the draw //State, otherwise measure state would suffice. span.updatedrawstate (WP); } & nbsp; } Ok, finally found the source of the span.
we can summarize the TextView drawing process.
TextView's OnDraw----"Draw----of layout" Textline draw----"Characterstyleupdatedrawstate (if a span style is set)
The main code drawn is also in draw of layout and textline draw.
from the inheritance structure of the class, my simple Characterstyle is divided into two categories: one directly inherits Characterstyle, the otherReplacementspan. The first: the style that directly inherits Characterstyle is mainly related to paint, and you only need to change the settings in the brush to achieve the purpose of the change. The second type: InheritanceReplacementspan, inthere are draw methods in the Replacementspan, Public Abstract voidDraw (Canvas canvas, charsequence text, int start, int end, float x, int top, int y, int bottom, paint paint);we can directly through the operation of canvas to draw their own, how do you want to draw, not completely listen to you??? after the classification, we can understand that if you need to customize the span later, you can selectively inherit the class.
From for notes (Wiz)
An analysis of the span style source code for Android TextView