美文网首页Android杂识Android知识Android开发
项目需求讨论: 文字显示排版— Html 格式

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

作者: 青蛙要fly | 来源:发表于2017-04-14 14:45 被阅读663次

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

    比如


    升级更新框升级更新框
    通知提示框通知提示框

    我们看到,我用红框框出来的地方
    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格式的文字呈现效果。


    继续放招

    我们用如下代码:

    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。


    老司机最后一招

    大家都知道,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哈哈~

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/yviwattx.html