Android的TextView显示HTML格式富文本(字体大小颜色图片图文混排等)

  • A+
所属分类:Android

传统上TextView一般都是比较简单的使用,展示一下文字,文字的字体、颜色等也是直接在xml里设置。这种使用对大家来说不是问题,但TextView也有一些更复杂、更高级的使用,例如显示HTML格式的富文本。

首先,为什么还要用TextView来显示html富文本呢?这里就有比较多的考量了:商品的详情页面,显示富文本、甚至显示一个比较复杂的html页面内容,都是很常见的需求。一般来说,使用WebView是最直截了当的办法,不过大家也知道,Android的WebView着实有不少的坑,无论是不同Android版本还是其本身的资源回收等问题,都让众多Android开发人苦不堪言,而且详情展示通常只是展示,并不需要过多的类似于浏览器的用户操作。而展示同样的内容,使用TextView和WebView在内存资源上的占用显然也不是一个级别。简而言之,如果能用TextView来显示富文本,要比WebView好得多。

我们知道,给TextView设置显示内容,是通过setText(CharSequence text)方法实现的。下面看一下该方法的源码:

该方法接受的参数是CharSequence,而String就是它的实现,所以我们平时都是直接setText(“字符串”)的形式来设置文本。需要注意的是,setText(CharSequence text)方法的注释很重要,值得我们好好看一下。其中,“TextView <em>does not</em> accept
* HTML-like formatting, which you can do with text strings in XML resource files.”这句注释是跟我们今天的主题相关的,人家明明白白说了,TextView不支持HTML格式的文本,好吧,难道这样就走入死胡同了?

当然不会了。在android.text包下有个Html类,提供了多个fromHtml的方法,我们先看一下只有一个参数的:

虽然该方法已经deprecated了,但从它的注释中,我们可以看到,该方法输入的参数就是HTML格式的字符串,而返回的就是可显示的、带样式的文本。什么是样式?比如字体颜色大小,甚至加粗、下划线等。至于返回数据的类型Spanned,我们继续看它的源码,可知Spanned是一个带标记的文本接口,也是继承自CharSequence的。OK,既然它继承自CharSequence,那么作为setText的参数似乎是没问题的。

只说话不上代码岂是我辈风格?我们弄一个简单的富文本字符串:

首先,我们用最普通的方式,直接把这段字符串通过setText的方法设置给TextView(其他代码如setContentView等就不给出来了):

直接把html富文本设置给TextView

结果就是TextView十分诚实的把你设置的字符串,很直接的显示了出来,显然这不是我们想要的结果。下面我们就用Html.fromHtml了:

通过Html.fromHtml设置富文本

很好,可以看到HTML格式的文字被正确显示了,这里包括加粗的<b>标签,段落<p>标签,1级标题<h1>标签,以及字体<font>与相应的字号、颜色等,都很好的显示了出来,与浏览器无异。不过,图片标签<img>那里,似乎并不是我们想要的结果。我们再看一下另一个fromHtml方法:

该方法同样可以处理HTML格式的富文本,而且还能依赖你指定的ImageGetter实现图片的加载。如果ImageGetter为null呢?

可以看到这个方法就是调用了fromHtml(String source, int flags, ImageGetter imageGetter, TagHandler tagHandler)方法,且ImageGetter为null的。此时<img>标签的图片不会被加载出来,而是显示为一个通用的替代图片,就是截图里那一小块绿色喽。为了能顺利显示图片,我们来看看ImageGetter是什么东西:

原来是一个只有一个getDrawable方法的接口,实现该接口的目的就是为了获取HTML中<img>标签下的图片,需要注意的是,该方法的source参数已经被系统处理过了,就是从<img>标签里获取道的src属性,也就是图片的地址了,不需要我们做额外处理。下面我们写一个简单的实现:

然后不出所料的,你会得到一个android.os.NetworkOnMainThreadException的错误。为什么?很显然,Drawable.createFromStream(new URL(source).openStream(), "");这里是从网上下载图片,刚才的代码很直接的写在了主线程里。而Android不允许在主线程里访问网络(应该是4.0时候的改动吧),所以需要用子线程:

这里我们在Thread里下载图片,最终通过Handler在主线程里设置,来看看运行结果:

简单的ImageGetter获取HTML富文本里的图片

OK!这下子得到我们想要的结果了。

KaelLi

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: