项目需求讨论: 文字显示排版— Html 格式

嗨,各位,今天来个小技巧,估计很多人都知道,我也就重复提下罢了。。

比如


升级更新框

通知提示框

我们看到,我用红框框出来的地方
1.直接使用系统自带的AlertDialog的提示框,我们看到了我们更新提示里面的具体内容是(-Bug修改 -新增更新提示);并且换行了。

2.是自定义的弹框,(自定义弹框用的是我自己封装的类:项目需求讨论-Android 自定义Dialog实现步骤及封装),我们看到里面的内容会有各种排版,有些是黑色加粗,有些是换行。有些字体可能颜色不同突出明显,等等需求。

归结

归结起来,我们不可能是好几个TextView,然后去自己一个段落一个TextView去呈现,一般都是跟后台约定好,让他传过来HTML格式的字符串

所以1.里面我们就是

AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(Html.fromHtml(info.getChangeLog()));

2.里面我们是

TextView message = (TextView) view.findViewById(R.id.message);
if(!TextUtils.isEmpty(content)){
    message.setText(Html.fromHtml(content));
}

所以后台传过来的时候,就是可能是这种

{"content":"<strong><big>低**</big></strong>:本月销售业绩。<br/><br/><strong>诺**</strong>:本月销售业"}

然后我们就一个TextView就可以呈现不同的格式的内容。只要用Html.fromHtml(String);先转一下,再赋给TextView即可。


老司机这就完了?????

答案当然是No。
你会发现Html.fromHtml(String message)这个方法画了横线,已经过时了。WHF。那应该用什么。

@SuppressWarnings("deprecation")
public static Spanned fromHtml(String html){
    Spanned result;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
       result = Html.fromHtml(html,Html.FROM_HTML_MODE_LEGACY);
    } else {
       result = Html.fromHtml(html);
    }
    return result;
}

我们在Android 6 及以下,还是使用Html.fromHtml(String);而在Android 7 及以上要用新的:Html.fromHtml(String , flags);
这个Config分为哪些呢:

官方链接走起:Html class documentation

flags有这些:

public static final int FROM_HTML_MODE_COMPACT = 63;
public static final int FROM_HTML_MODE_LEGACY = 0;
public static final int FROM_HTML_OPTION_USE_CSS_COLORS = 256;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE = 32;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_DIV = 16;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_HEADING = 2;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST = 8;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM = 4;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH = 1;
public static final int TO_HTML_PARAGRAPH_LINES_CONSECUTIVE = 0;
public static final int TO_HTML_PARAGRAPH_LINES_INDIVIDUAL = 1;

看了还是不懂,没关系。效果图放出来:

<p style="color: blue;">This is a paragraph with a style</p>

<h4>Heading H4</h4>

<ul>
   <li style="color: yellow;">
      <font color=\'#FF8000\'>li orange element</font>
   </li>
   <li>li #2 element</li>
</ul>

<blockquote>This is a blockquote</blockquote>

Text after blockquote
Text before div

<div>This is a div</div>

Text after div

不同Config的情况下显示的Html格式的文字呈现效果。

image

继续放招

我们用如下代码:

String message = "<strong><big>低**</big></strong>:本月销售业绩。<br/><br/><strong>诺**</strong>:本月销售业";

textView.setText(Html.fromHtml(message));

OK,没问题。我们知道会出来我们上面的自定义提示框的格式。
但是我们如果是

textView.setText(Html.fromHtml(message)+"");

没错,我们把Html.fromHtml(message)和字符串拼接之后,再传给TextView,那么那些<strong>,<big>等标签就无效了。<br/>还是有效。

所以我们如果有需求要拼接字符串,一定要先把要拼接的字符串拼接完后,再用Html.fromHtml包裹,然后赋值给TextView。

有些人说我的字符串不是在代码中,而是在strings.xml中定义,但是直接XML中的<string>标签里面定义很多其他标签:<font>......。在低版本的Android设备可能会直接忽略这些标签,这时候我们可以使用<![CDATA[]]>,这个标记所包含的内容将表示为纯文本。
比如: <string name="xx"><![CDATA[ 没颜色 <font color=#B0CB4A>有颜色的文字</font> <br/> 换一行显示 <br/> 再换一行显示]]></string>


老司机最后一招

大家都知道,Html格式中改变字体大小的是<font size = "20"></font>但是你会发现:

String htmlText = "<font color=#000000 size=18px>"+productName+"</font> <br/><br/>"
+ "<font color=#ff6600 size=18px>积分:</font>"
+ "<font color=#ff6600 size=20px>+"+productPoint+"分</font>";  

TextView tv = (TextView)findViewById(R.id.productNameAndPoint);
tv.setText(Html.fromHtml(htmlText));

我们的颜色<font color = "#123456">的设置是有效的,但是<font size = "20">却无效。

解决方法:
1.如果项目的字体大小要求不是很精致,只是单纯的为了标题突出等,可以用我们上面的<big>,<strong>,<small>
2.我们自定义标签。思路是替换font标签自己解析设置。用到的接口是Html类TagHandler接口:

public class DdbFontHandler implements TagHandler {  
  
    private int startIndex = 0;  
    private int stopIndex = 0;  
  
    @Override  
    public void handleTag(boolean opening, String tag, Editable output,  
            XMLReader xmlReader) {  
        processAttributes(xmlReader);  
          
        if(tag.equalsIgnoreCase("ddbfont")){  
            if(opening){  
                startFont(tag, output, xmlReader);  
            }else{  
                endFont(tag, output, xmlReader);  
            }  
        }  
  
    }  
      
    public void startFont(String tag, Editable output, XMLReader xmlReader) {    
        startIndex = output.length();    
    }    
    
    public void endFont(String tag, Editable output, XMLReader xmlReader){    
        stopIndex = output.length();    
          
        String color = attributes.get("color");  
        String size = attributes.get("size");  
        size = size.split("px")[0];  
        if(!TextUtils.isEmpty(color) && !TextUtils.isEmpty(size)){  
            output.setSpan(new ForegroundColorSpan(Color.parseColor(color)), startIndex, stopIndex,  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);    
            output.setSpan(new AbsoluteSizeSpan(Utils.dipToPx(GApp.instance(), Integer.parseInt(size))), startIndex, stopIndex,  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);    
        }else{  
            output.setSpan(new ForegroundColorSpan(0xff2b2b2b), startIndex, stopIndex,  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);    
        }  
    }   
      
    final HashMap<String, String> attributes = new HashMap<String, String>();  
  
    private void processAttributes(final XMLReader xmlReader) {  
        try {  
            Field elementField = xmlReader.getClass().getDeclaredField("theNewElement");  
            elementField.setAccessible(true);  
            Object element = elementField.get(xmlReader);  
            Field attsField = element.getClass().getDeclaredField("theAtts");  
            attsField.setAccessible(true);  
            Object atts = attsField.get(element);  
            Field dataField = atts.getClass().getDeclaredField("data");  
            dataField.setAccessible(true);  
            String[] data = (String[])dataField.get(atts);  
            Field lengthField = atts.getClass().getDeclaredField("length");  
            lengthField.setAccessible(true);  
            int len = (Integer)lengthField.get(atts);  
  
            /** 
             * MSH: Look for supported attributes and add to hash map. 
             * This is as tight as things can get :) 
             * The data index is "just" where the keys and values are stored.  
             */  
            for(int i = 0; i < len; i++)  
                attributes.put(data[i * 5 + 1], data[i * 5 + 4]);  
        }  
        catch (Exception e) {  
        }  
    }  
  
}  

还有超链接等其他的HTML标签的实现:

请参考:Html类TagHandler接口


哪里错了希望大家用力喷我!!! O(∩_∩)O哈哈~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,327评论 0 17
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • #Android 基础知识点总结 ---------- ##1.adb - android debug bridg...
    Mythqian阅读 3,220评论 2 11
  • 这一晚你一定很兴奋吧?终于野外露营了,盼了三年。 还记得三年前暑假,你回到我身边,我联系几个地方露营都未果,还遭到...
    hh与ww阅读 217评论 0 1
  • 昨天晚上梦到了我哥,听着他模糊的话语,对我的声声控诉,真是心如刀割。想想自己是要努力工作,为了孩子,更是为了自己。...
    芳老头阅读 247评论 0 0