android textview shows html method resolution

  • 2020-05-05 11:52:04
  • OfStack

In the age of the Internet, text alone is not enough to satisfy people's appetite. Pictures, flash, audio and video have become the mainstream of web browsing, even on mobile phones. The data obtained from the network side of the display on the phone shows that people naturally think of two ways, one is webview, one is TextView. Of course, webView directly displays html page, I mainly said TextView shows html content.
First, let's talk about which tags TextView actually supports. By looking at the source code, we found that Textview can parse some html tags, such as
 
<a href="..."> 
<b> 
<big> 
<blockquote> 
<br> 
<cite> 
<dfn> 
<div align="..."> 
<em> 
<font size="..." color="..." face="..."> 
<h1> 
<h2> 
<h3> 
<h4> 
<h5> 
<h6> 
<i> 
<img src="..."> 
<p> 
<small> 
<strike> 
<strong> 
<sub> 
<sup> 
<tt> 
<u> 

You want to look at it can see android.text.Html source code, which has a paragraph like this:
 
private void handleStartTag(String tag, Attributes attributes) { 
if (tag.equalsIgnoreCase("br")) { 
// We don't need to handle this. TagSoup will ensure that there's a </br> for each <br> 
// so we can safely emite the linebreaks when we handle the close tag. 
} else if (tag.equalsIgnoreCase("p")) { 
handleP(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("div")) { 
handleP(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("em")) { 
start(mSpannableStringBuilder, new Bold()); 
} else if (tag.equalsIgnoreCase("b")) { 
start(mSpannableStringBuilder, new Bold()); 
} else if (tag.equalsIgnoreCase("strong")) { 
start(mSpannableStringBuilder, new Italic()); 
} else if (tag.equalsIgnoreCase("cite")) { 
start(mSpannableStringBuilder, new Italic()); 
} else if (tag.equalsIgnoreCase("dfn")) { 
start(mSpannableStringBuilder, new Italic()); 
} else if (tag.equalsIgnoreCase("i")) { 
start(mSpannableStringBuilder, new Italic()); 
} else if (tag.equalsIgnoreCase("big")) { 
start(mSpannableStringBuilder, new Big()); 
} else if (tag.equalsIgnoreCase("small")) { 
start(mSpannableStringBuilder, new Small()); 
} else if (tag.equalsIgnoreCase("font")) { 
startFont(mSpannableStringBuilder, attributes); 
} else if (tag.equalsIgnoreCase("blockquote")) { 
handleP(mSpannableStringBuilder); 
start(mSpannableStringBuilder, new Blockquote()); 
} else if (tag.equalsIgnoreCase("tt")) { 
start(mSpannableStringBuilder, new Monospace()); 
} else if (tag.equalsIgnoreCase("a")) { 
startA(mSpannableStringBuilder, attributes); 
} else if (tag.equalsIgnoreCase("u")) { 
start(mSpannableStringBuilder, new Underline()); 
} else if (tag.equalsIgnoreCase("sup")) { 
start(mSpannableStringBuilder, new Super()); 
} else if (tag.equalsIgnoreCase("sub")) { 
start(mSpannableStringBuilder, new Sub()); 
} else if (tag.length() == 2 && 
Character.toLowerCase(tag.charAt(0)) == 'h' && 
tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 
handleP(mSpannableStringBuilder); 
start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1')); 
} else if (tag.equalsIgnoreCase("img")) { 
startImg(mSpannableStringBuilder, attributes, mImageGetter); 
} else if (mTagHandler != null) { 
mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader); 
} 
} 
private void handleEndTag(String tag) { 
if (tag.equalsIgnoreCase("br")) { 
handleBr(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("p")) { 
handleP(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("div")) { 
handleP(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("em")) { 
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 
} else if (tag.equalsIgnoreCase("b")) { 
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 
} else if (tag.equalsIgnoreCase("strong")) { 
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
} else if (tag.equalsIgnoreCase("cite")) { 
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
} else if (tag.equalsIgnoreCase("dfn")) { 
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
} else if (tag.equalsIgnoreCase("i")) { 
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 
} else if (tag.equalsIgnoreCase("big")) { 
end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f)); 
} else if (tag.equalsIgnoreCase("small")) { 
end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f)); 
} else if (tag.equalsIgnoreCase("font")) { 
endFont(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("blockquote")) { 
handleP(mSpannableStringBuilder); 
end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan()); 
} else if (tag.equalsIgnoreCase("tt")) { 
end(mSpannableStringBuilder, Monospace.class, 
new TypefaceSpan("monospace")); 
} else if (tag.equalsIgnoreCase("a")) { 
endA(mSpannableStringBuilder); 
} else if (tag.equalsIgnoreCase("u")) { 
end(mSpannableStringBuilder, Underline.class, new UnderlineSpan()); 
} else if (tag.equalsIgnoreCase("sup")) { 
end(mSpannableStringBuilder, Super.class, new SuperscriptSpan()); 
} else if (tag.equalsIgnoreCase("sub")) { 
end(mSpannableStringBuilder, Sub.class, new SubscriptSpan()); 
} else if (tag.length() == 2 && 
Character.toLowerCase(tag.charAt(0)) == 'h' && 
tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 
handleP(mSpannableStringBuilder); 
endHeader(mSpannableStringBuilder); 
} else if (mTagHandler != null) { 
mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader); 
} 
} 

As you can see from the source code, in addition to some default tags, it also supports custom tags; See the following code:
else if (mTagHandler != null) {
mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader);
}
The system calls the handleTag method of mTagHandler. So, we can implement this interface to parse our own defined tag types.
Specifically, you can look at the following example:
 
package com.mxgsa.tvimg; 
import org.xml.sax.XMLReader; 
import android.content.Context; 
import android.content.Intent; 
import android.text.Editable; 
import android.text.Html.TagHandler; 
import android.text.Spanned; 
import android.text.style.ClickableSpan; 
import android.view.View; 
import android.view.View.OnClickListener; 
public class MxgsaTagHandler implements TagHandler{ 
private int sIndex = 0; 
private int eIndex=0; 
private final Context mContext; 
public MxgsaTagHandler(Context context){ 
mContext=context; 
} 
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { 
// TODO Auto-generated method stub 
if (tag.toLowerCase().equals("mxgsa")) { 
if (opening) { 
sIndex=output.length(); 
}else { 
eIndex=output.length(); 
output.setSpan(new MxgsaSpan(), sIndex, eIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
} 
} 
} 
private class MxgsaSpan extends ClickableSpan implements OnClickListener{ 
@Override 
public void onClick(View widget) { 
// TODO Auto-generated method stub 
// Specific code, can be a jump page, can be a pop-up dialog box, the following is the jump page  
mContext.startActivity(new Intent(mContext,MainActivity.class)); 
} 
} 
} 

Call page:
 
package com.mxgsa.tvimg; 
import android.app.Activity; 
import android.os.Bundle; 
import android.text.Html; 
import android.text.method.LinkMovementMethod; 
import android.widget.TextView; 
public class MxgsaActivity extends Activity{ 
private TextView tView; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.mxgsa_activity); 
findControl(); 
setData(); 
} 
private void findControl() { 
tView = (TextView) findViewById(R.id.tvImage); 
} 
private void setData() { 
// TODO Auto-generated method stub 
final String sText = " Test custom tags: <br><h1><mxgsa> Test the custom tag </mxgsa></h1>"; 
tView.setText(Html.fromHtml(sText, null, new MxgsaTagHandler(this))); 
tView.setClickable(true); 
tView.setMovementMethod(LinkMovementMethod.getInstance()); 
} 
} 

The next article will talk about html text display with pictures! To be continued...

Related articles: