Android uses Span rich text to process Html tags

(Written before the question, the Html.fromHtml() method can also implement the function of processing html tags, but it is generally applicable to the simplest functional requirements for displaying text content. If TextView itself has other effects that need to be customized and have already been used The processing or effect of Span is related to the actual effective length of the text content itself (the label itself is not a valid content), which may be very limited by using Html.fromHtml(). In fact, it is more flexible to use 

Span rich text to process html tags. ) 


Let me talk about the conclusion first, and go directly to the code. 
String title="xxxxxxx";//It contains tags such as <sub></sub> 
tv.setText(getTabSpan(title,tv.getPaint()); 
/** 
 * Processing tags such as <sup></sup> 
 * @param title 
 * @param textPaint 
 * @return 
 */ 
public static SpannableStringBuilder getTabSpan(String title, TextPaint textPaint) { 

    SpannableStringBuilder spanBuilder=new SpannableStringBuilder(title); 
    spanBuilder=getHtmlSpan(spanBuilder,textPaint,"<sup>","</ sup>");
    spanBuilder=getHtmlSpan(spanBuilder,textPaint,"<strong>","</strong>");
    //期待更多支持的标签。。。
    return spanBuilder;
}
private static SpannableStringBuilder getHtmlSpan(SpannableStringBuilder spanBuilder, TextPaint textPaint,String pre,String suffix) {
    int fontSizeSp=(int)(textPaint.getTextSize()/textPaint.density);
    String key=pre+"(.+?)"+suffix;
    CharacterStyle span;
    Pattern p;
    int preLength=pre.length();
    int suffixLength=suffix.length();
    String title=spanBuilder.toString();
    try {
        p = Pattern.compile(key);
        Matcher m = p.matcher(title);
        //LogSuperUtil.i("cnki_wiki_data","fontSizeSp="+fontSizeSp);
        while (m.find()) {
            int startIndex=m.start(); 
            int endIndex=m.end();//It is the position where the expression ends, not the position where the suffix begins. 
            int spanStartIndex=startIndex+preLength; 
            int spanEndIndex=endIndex-suffixLength; 
            if("<sup>".equals(pre)) { 
                span = new SuperscriptSpan();// Need to repeat! 
                spanBuilder.setSpan(span,spanStartIndex,spanEndIndex,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
                AbsoluteSizeSpan sizeSpan=new AbsoluteSizeSpan(fontSizeSp,false); 
                spanBuilder.setSpan(sizeSpan,spanStartIndex,spanEndIndex, Spannable .SPAN_EXCLUSIVE_EXCLUSIVE); 
            }else if("<sup>" .equals(pre)) { 
                span = new SuperscriptSpan();// Need to repeat!
                spanBuilder.setSpan(span,spanStartIndex,spanEndIndex,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                AbsoluteSizeSpan sizeSpan=new AbsoluteSizeSpan(fontSizeSp,false);
                spanBuilder.setSpan(sizeSpan,spanStartIndex,spanEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }else if("<strong>".equals(pre)) {
                span = new StyleSpan(android.graphics.Typeface.BOLD);// 需要重复!
                spanBuilder.setSpan(span,spanStartIndex,spanEndIndex,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            //LogSuperUtil.i("cnki_wiki_data","上标 start="+start+",end="+end);*/
            spanBuilder.delete(endIndex-suffixLength,endIndex);
            spanBuilder.delete(startIndex,startIndex+preLength);
            title=spanBuilder.toString();
            m=p.matcher(title);
        }

    } catch (Exception e) {
        p = Pattern.compile("[^0-9]");
    }
    return spanBuilder;
}

The most important thing is the architectural design, the idea, and of course the most important technical points.

To sum up from the pits that have been stepped on, several important knowledge points need to be known.

1. The delete method of SpannableStringBuilder will not affect the rich text effect already set, and the index will not be automatically shifted. This ensures that after processing the text of <sup>15</sup>N degrees, deleting the characters "<sup>" and "</sup>" will not affect the superscript effect of the word "15".

2.SpannableStringBuilder spanBuilder=new SpannableStringBuilder(charSq);

If charSq is already a rich text, then spanBuilder will not destroy the existing rich text effect.

Of course, in this example, on the basis of 1, the use of 2 may not be used. Because you get the instance reference of SpannableStringBuilder, you can process the desired rich text effect multiple times.

In addition, when realizing the effect of keyword processing highlighting and marking red, there is also a summary of the application of regular expressions.

The code is like this:

private  SpannableStringBuilder getKeywordSpan(SpannableStringBuilder spanBuilder) {
    String pre="###";
    String suffix="\\$\\$\\$";
    String key=pre+"(.+?)"+suffix;
    CharacterStyle span;
    Pattern p;
    int preLength=pre.length();
    int suffixLength=suffix.length();
    suffixLength=3;//强制
    String title=spanBuilder.toString();
    try {
        p = Pattern.compile(key);
        Matcher m = p.matcher(title);
        int color=mContext.getResources().getColor(R.color.red);
        //LogSuperUtil.i("cnki_wiki_data","fontSizeSp="+fontSizeSp);
        while (m.find()) {
            int startIndex=m.start();
            int endIndex=m.end();//It is the position where the expression ends, not the position where the suffix begins. 
            int spanStartIndex=startIndex+preLength; 
            int spanEndIndex=endIndex-suffixLength; 
            span = new ForegroundColorSpan(color);// Need to repeat! 
            spanBuilder.setSpan(span, spanStartIndex, spanEndIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
            //LogSuperUtil.i("cnki_wiki_data", "superscript start="+start+", end="+end);*/ 
            spanBuilder.delete(spanEndIndex, endIndex); 
            spanBuilder.delete(startIndex,spanStartIndex); 
            title=spanBuilder.toString(); 
            m=p.matcher(title); 
        } 

    } catch (Exception e) { 
        p = Pattern.compile("[^0-9] ");
    return spanBuilder;
}

In fact, it matches "###xx$$$". Since the symbol $ indicates the end of the expression in the regular expression, it needs to be escaped, and \$ is the $ itself. In Java, the \ character itself is also a special character and needs to be escaped. What \\ represents is the real \ character. Therefore, if you want to really represent the $ character in a regular expression, you must write it as \\ in the regular expression $, this has the way of writing in the code.

After matching, process the string "###xx$$$", the length of the string to be deleted is 3 (the length of "$$$"), not "\$\$\$" (in fact, it will It is found that Match matches "\$\$\$").

This is a good choice when you need to display tags in Html in the future, especially when the custom TextView itself has used Span to process things, such as implementing "... expand".

Guess you like

Origin blog.csdn.net/yeziyfx/article/details/126417495