优秀的编程知识分享平台

网站首页 > 技术文章 正文

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

nanyue 2024-09-14 06:19:59 技术文章 5 ℃

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>}
1

下面的示例来介绍如何在 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();
}
1234567

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();
12345678910

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) {
……
 }
123456789101112

最后,在完成了 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);
123

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;
        }
    }
}
123456789101112131415161718192021222324252627282930313233
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);
        }

    }

}
最近发表
标签列表