TextView实现Android图文混排显示HTML内容

    科技2026-01-21  10

    Android 中的 TextView 组件常用于显示文本内容,其实它也可以显示 HTML 的内容。简单来讲,这就需要先把 HTML 的内容以字符串的形式获取后,经过 android.text.Html.fromHtml()转化成 Spanned 的格式,然后将其传递到 TextView 的 setText()方法中,这样就可以在 TextView 中显示 HTML 页面的内容了。需要注意的是,并不是所有的 HTML 标签在 TextView 中都是支持的,且官方文档并没有明确的说明支持 HTML 标签列表,通过查看 Android 源代码,可以得到简单的支持列表。

    {<br>,< p>,< div align=>,< strong>, <b>, <em>, <cite>, <dfn>, <i>, <big>, <small>, <font size=>, <font color=>, <blockquote>, <tt>, <a href=>, <u>, <sup>, <sub>, <h1>,<h2>,<h3>,<h4>,<h5>,<h6>, <img src=>, <strike>}

    下面的示例来介绍如何在 TextView 中显示一段 HTML 内容,要显示的这段 HTML 内容即包含超链接内容,也包含有图片。 在 TextView 中显示 HTML 内容

    显示的过程中最主要的过程就是调用 Android.text.Html 类提供的 fromHtml()方法,将一段 HTML 内容转化为 Spanned 对象。

    Android.text.Html 类提供的 fromHtml()方法使用如下清单 4 fromHtml()方法定义

    public static Spanned fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler) { …… HtmlToSpannedConverter converter = new HtmlToSpannedConverter(source, imageGetter, tagHandler, parser); return converter.convert(); }

    source,就是包含 HTML 内容的字符串。而 Html.ImageGetter 和 Html.TagHandler 是两个接口,提供给开发者继承使用。 imageGetter, 如果要显示图片是需要被继承的,重写 getDrawable(String source)方法,用于获取 HTML 里面的图片来显示在 TextView 中。 tagHandler,其作用是把 HTML 带标记的文本内容字符串转化成可以显示效果的的 Spanned 字符串 。由于并非所有的 HTML 标签都可以转化,所以在使用时,用户需要自己添加一些必要的标签和处理方法时才会继承使用的。

    在本例中使用 fromHtml()方法之前,要准备好该方法要用的三个参数内容,首先将 HTML 字符串内容准备好,在项目中需要创建两个类 MImageGetter 和 MTagHandler 分别继承于 ImageGetter 和 TagHandler,分别用户图片的获取,和特殊标签的支持。 MImageGetter

    继承于 ImageGetter,重写 getDrawable (String source) 方法中从 assets 路径下取出的图片流(这里当然也可以通过网络操作来完成图片流的获取),最后获得可供显示的图片对象,例如 Drawable 对像。由于 Android 设备的异构性,为了有更好的显示效果,通常需要获取屏幕大小,然后调用 drawable.setBounds () 还可以重新设置图片的大小, 最后返回合适大小的图片 Drawable 对象。 由此 Spanned 中的 ImageSpan 就获得了图像被显示在 TextView 中对应位置了。

    TypedValue typedValue = new TypedValue(); typedValue.density = TypedValue.DENSITY_DEFAULT; drawable = Drawable.createFromResourceStream(null, typedValue, is, "src"); DisplayMetrics dm = c.getResources().getDisplayMetrics(); int dwidth = dm.widthPixels-10;//padding left + padding right float dheight = (float)drawable.getIntrinsicHeight()*(float)dwidth/(float)drawable.getIntrinsicWidth(); int dh = (int)(dheight+0.5); int wid = dwidth; int hei = dh; drawable.setBounds(0, 0, wid, hei);DisplayMetrics dm = c.getResources().getDisplayMetrics();

    MTagHandler

    继承于 TagHandler,重写了 handleTag()方法,为的是支持部分标签,这四个标签是在 formHtml()方法中本身是不支持。如果开发者认为安卓 TagHandler 提供的默认标签解析已经够用,直接在 fromHtml()方法中第三个参数的地方填写 null 既可。 重写 handleTag()方法

    public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) { if (tag.equals("ul") || tag.equals("ol") || tag.equals("dd")) { if (opening) { mListParents.add(tag); } else mListParents.remove(tag); } else if (tag.equals("li") && !opening) { handleListTag(output); } } private void handleListTag(Editable output) { …… }

    最后,在完成了 MImageGetter、MTagHandler 以后,就可以通过 formHtml()方法将 HTML 内容转化为可供显示的 SpannableString,将 SpannableString 通过 setText 方法放入 TextView 中,就可以显示图文并茂的内容了。

    progressBar.setVisibility(View.GONE); text.setText(Html.fromHtml(htmlCont, new MImageGetter(text,MainActivity.this), new MTagHandler())); text.setVisibility(View.VISIBLE);

    MImageGetter、MTagHandler 如下:

    public class MImageGetter implements Html.ImageGetter { Context c; public MImageGetter(TextView text, Context c) { this.c = c; } public Drawable getDrawable(String source) { Drawable drawable = null; InputStream is = null; try { is = this.c.getResources().getAssets().open(source); } catch (IOException var12) { var12.printStackTrace(); } try { TypedValue typedValue = new TypedValue(); typedValue.density = 0; drawable = Drawable.createFromResourceStream((Resources)null, typedValue, is, "src"); DisplayMetrics dm = this.c.getResources().getDisplayMetrics(); int dwidth = dm.widthPixels - 10; float dheight = (float)drawable.getIntrinsicHeight() * (float)dwidth / (float)drawable.getIntrinsicWidth(); int dh = (int)((double)dheight + 0.5D); drawable.setBounds(0, 0, dwidth, dh); return drawable; } catch (Exception var11) { System.out.println(var11); return null; } } } public class MTagHandler implements Html.TagHandler { private int mListItemCount = 0; private Vector<String> mListParents = new Vector(); public MTagHandler() { } public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if (!tag.equals("ul") && !tag.equals("ol") && !tag.equals("dd")) { if (tag.equals("li") && !opening) { this.handleListTag(output); } } else { if (opening) { this.mListParents.add(tag); } else { this.mListParents.remove(tag); } this.mListItemCount = 0; } } private void handleListTag(Editable output) { String[] split; int lastIndex; int start; if (((String)this.mListParents.lastElement()).equals("ul")) { output.append("\n"); split = output.toString().split("\n"); lastIndex = split.length - 1; start = output.length() - split[lastIndex].length() - 1; output.setSpan(new BulletSpan(15 * this.mListParents.size()), start, output.length(), 0); } else if (((String)this.mListParents.lastElement()).equals("ol")) { ++this.mListItemCount; output.append("\n"); split = output.toString().split("\n"); lastIndex = split.length - 1; start = output.length() - split[lastIndex].length() - 1; output.insert(start, this.mListItemCount + ". "); output.setSpan(new Standard(15 * this.mListParents.size()), start, output.length(), 0); } } }
    Processed: 0.014, SQL: 9