Android中Textview显示带html文本-------【HTML标签】
来源:互联网 发布:ug8.5数控编程实例 编辑:程序博客网 时间:2024/05/14 22:59
现在网络的繁盛时代,光文字是不能满足人们的胃口的,图片,flash,音频,视频就成为浏览网页的主流显示,在手机上也一样。在手机上显示从网络端获取的数据显示,大家很自然的想起两种方式,一种就是webview,一种就是TextView。当然webView直接显示html页面就行了,我主要说的TextView显示html内容。
首先,说下TextView到底支持那些标签呢,通过对源码的查看,发现Textview可以解析一部分html标签,如:
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font size="..." color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>
大家想究其根本可以查看android.text.Html源码,其中有一段这样写:
if (tag.equalsIgnoreCase("br")) {
// We don't need to handle this. TagSoup will ensure that there's a </br> for each <br>
// so we can safely emite the linebreaks when we handle the close tag.
} else if (tag.equalsIgnoreCase("p")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("div")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("em")) {
start(mSpannableStringBuilder, new Bold());
} else if (tag.equalsIgnoreCase("b")) {
start(mSpannableStringBuilder, new Bold());
} else if (tag.equalsIgnoreCase("strong")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("cite")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("dfn")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("i")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("big")) {
start(mSpannableStringBuilder, new Big());
} else if (tag.equalsIgnoreCase("small")) {
start(mSpannableStringBuilder, new Small());
} else if (tag.equalsIgnoreCase("font")) {
startFont(mSpannableStringBuilder, attributes);
} else if (tag.equalsIgnoreCase("blockquote")) {
handleP(mSpannableStringBuilder);
start(mSpannableStringBuilder, new Blockquote());
} else if (tag.equalsIgnoreCase("tt")) {
start(mSpannableStringBuilder, new Monospace());
} else if (tag.equalsIgnoreCase("a")) {
startA(mSpannableStringBuilder, attributes);
} else if (tag.equalsIgnoreCase("u")) {
start(mSpannableStringBuilder, new Underline());
} else if (tag.equalsIgnoreCase("sup")) {
start(mSpannableStringBuilder, new Super());
} else if (tag.equalsIgnoreCase("sub")) {
start(mSpannableStringBuilder, new Sub());
} else if (tag.length() == 2 &&
Character.toLowerCase(tag.charAt(0)) == 'h' &&
tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
handleP(mSpannableStringBuilder);
start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1'));
} else if (tag.equalsIgnoreCase("img")) {
startImg(mSpannableStringBuilder, attributes, mImageGetter);
} else if (mTagHandler != null) {
mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);
}
}
private void handleEndTag(String tag) {
if (tag.equalsIgnoreCase("br")) {
handleBr(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("p")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("div")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("em")) {
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
} else if (tag.equalsIgnoreCase("b")) {
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
} else if (tag.equalsIgnoreCase("strong")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("cite")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("dfn")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("i")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("big")) {
end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f));
} else if (tag.equalsIgnoreCase("small")) {
end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f));
} else if (tag.equalsIgnoreCase("font")) {
endFont(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("blockquote")) {
handleP(mSpannableStringBuilder);
end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan());
} else if (tag.equalsIgnoreCase("tt")) {
end(mSpannableStringBuilder, Monospace.class,
new TypefaceSpan("monospace"));
} else if (tag.equalsIgnoreCase("a")) {
endA(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("u")) {
end(mSpannableStringBuilder, Underline.class, new UnderlineSpan());
} else if (tag.equalsIgnoreCase("sup")) {
end(mSpannableStringBuilder, Super.class, new SuperscriptSpan());
} else if (tag.equalsIgnoreCase("sub")) {
end(mSpannableStringBuilder, Sub.class, new SubscriptSpan());
} else if (tag.length() == 2 &&
Character.toLowerCase(tag.charAt(0)) == 'h' &&
tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
handleP(mSpannableStringBuilder);
endHeader(mSpannableStringBuilder);
} else if (mTagHandler != null) {
mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader);
}
}
通过源码可以看到,除了默认的一些标签,其还支持自定义标签;看下面代码:
mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader);
}
系统会调用mTagHandler的handleTag方法。所以,我们可以实现此接口,来解析自己定义的标签类型。
具体的,自己可以看一下下面实例:
import org.xml.sax.XMLReader;
import android.content.Context;
import android.content.Intent;
import android.text.Editable;
import android.text.Html.TagHandler;
import android.text.Spanned;
import android.text.style.ClickableSpan;
import android.view.View;
import android.view.View.OnClickListener;
public class MxgsaTagHandler implements TagHandler{
private int sIndex = 0;
private int eIndex=0;
private final Context mContext;
public MxgsaTagHandler(Context context){
mContext=context;
}
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
// TODO Auto-generated method stub
if (tag.toLowerCase().equals("mxgsa")) {
if (opening) {
sIndex=output.length();
}else {
eIndex=output.length();
output.setSpan(new MxgsaSpan(), sIndex, eIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
private class MxgsaSpan extends ClickableSpan implements OnClickListener{
@Override
public void onClick(View widget) {
// TODO Auto-generated method stub
//具体代码,可以是跳转页面,可以是弹出对话框,下面是跳转页面
mContext.startActivity(new Intent(mContext,MainActivity.class));
}
}
}
调用页面:
import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
public class MxgsaActivity extends Activity{
private TextView tView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mxgsa_activity);
findControl();
setData();
}
private void findControl() {
tView = (TextView) findViewById(R.id.tvImage);
}
private void setData() {
// TODO Auto-generated method stub
final String sText = "测试自定义标签:<br><h1><mxgsa>测试自定义标签</mxgsa></h1>";
tView.setText(Html.fromHtml(sText, null, new MxgsaTagHandler(this)));
tView.setClickable(true);
tView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
下篇将会讲带图片的html文本显示!
Textview可以显示基本的HTML标签,如果不知道那些标签,可以查看Android中Textview显示带html文本一-------【HTML标签】!
下面着重说一下Textview显示“img”标签,也许看到这里,大家都会想到就是构建ImageGetter,重载一下其 public Drawable getDrawable(String source)方法,获取该路径的图片。
例如:
final Html.ImageGetter imageGetter = new Html.ImageGetter() { public Drawable getDrawable(String source) { return drawable; }; };
下面来说下public Drawable getDrawable(String source)这个方法,source就是图片路径!
例如:
final String sText = "测试图片信息:<br><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" /><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" />";tView.setText(Html.fromHtml(sText, imageGetter, null));
则source就是img的src的值,既是:http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg这个图片路径
当然这个<img src=路径/> 这个路径既可以是网络图片,也可以本地图片,项目资源图片
例如:本地图片<img src=\""/sdcard/images/test.jpg"\"/> 项目资源图片 <img src=\""+R.drawable.market_none_image+"\"/>
但是不同的路径,ImageGetter的重载处理方法都不一样,下面来一一介绍各种的处理方式.
第一种:本地图片
final String sText2 = "测试图片信息:<img src=\"/mnt/sdcard/temp/1.jpg\" />";tView.setText(Html.fromHtml(sText2, imageGetter, null));final Html.ImageGetter imageGetter = new Html.ImageGetter() { public Drawable getDrawable(String source) { Drawable drawable=null; drawable=Drawable.createFromPath(source); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); return drawable; };}
第二种:项目资源图片
final String sText1 = "测试图片信息:<img src=\""+R.drawable.market_none_image+"\" />";tView.setText(Html.fromHtml(sText1, imageGetter, null));final Html.ImageGetter imageGetter = new Html.ImageGetter() { public Drawable getDrawable(String source) { Drawable drawable=null; int rId=Integer.parseInt(source); drawable=getResources().getDrawable(rId); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); return drawable; };}
第三种:网络图片
final String sText = "测试图片信息:<br><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" />";tView.setText(Html.fromHtml(sText, imageGetter, null));final Html.ImageGetter imageGetter = new Html.ImageGetter() { public Drawable getDrawable(String source) { Drawable drawable=null; URL url; try { url = new URL(source); drawable = Drawable.createFromStream(url.openStream(), ""); } catch (Exception e) { e.printStackTrace(); return null; } drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); return drawable; };}
通过这三个方式,可以看出,不同的图片路径,得到图片的处理方式不同,大家也能一目了然的看出来ImageGetter是干什么的了,就是得到img中src所需的图片!
提醒一点:获取图片以后,一定要设置图片的边界,界线,即:drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());,不然获取图片后,Textview不能显示图片。
通过以上三种方式,是能可以显示出来图片,但是我发现了一个问题,就是第三种,显示网络图片,我用android2.3的系统,可以显示图片出来,并且如果图片比较大,应用会卡的现象,肯定是因为使用主线程去获取网络图片造成的,但如果我用android4.0以上的系统运行,则不能显示图片,只显示小方框。
究其原因,是在4.0的系统上执行的时候报错了,异常是:android.os.NetworkOnMainThreadException 经过查文档,原来是4.0系统不允许主线程(UI线程)访问网络,因此导致了其异常。说白了就是在主线程上访问网络,会造成主线程挂起,系统不允许使用了。
具体处理方式看下篇:Android中Textview显示带html文本三-------【Textview显示网络图片】
上篇遗留下来一个问题就是:显示网络图片,我用android2.3的系统,可以显示图片出来,并且如果图片比较大,应用会卡的现象,肯定是因为使用主线程去获取网络图片造成的,但如果我用android4.0以上的系统运行,则不能显示图片,只显示小方框。
究其原因,是在4.0的系统上执行的时候报错了,异常是:android.os.NetworkOnMainThreadException 经过查文档,原来是4.0系统不允许主线程(UI线程)访问网络,因此导致了其异常。说白了就是在主线程上访问网络,会造成主线程挂起,系统不允许使用了。
看到Android4.0不允许主线程(UI线程)访问网络,立马脑子就想起来 ,不能用主线程访问,可以开另外一个线程,把图片下到本地sd卡中,之后在赋值到TextView里面。不急着来代码,我和大家在把这个逻辑在理一下:获取图片路径——异步下载图片——完成下载后重新赋值Textview
想到这里,我就准备自己亲自实践下......于是,我就简单的写了文件下载类DownLoadUtils,有四个事件就是开始下载,下载中(返回进度),完成下载后,下载出错!具体代码就不贴出来了。大家可以自己去写一个,下载文件的代码搜下都有!下载类里面用到了线程和Handler的的使用,下篇我具体讲下这个。
下面是Activity页面处理代码:
下面来简单的介绍下上面的代码,最重要的就是有两点,就是第一次把sText赋值Textview,在Html.ImageGetter的重载方法里面去判断该图片文件是否已经下载,如果已经下载,就直接读取SD卡里面的图片文件,如上篇所讲的Textview显示本地图片,
//获取本地文件返回Drawable drawable=Drawable.createFromPath(fileString); //设置图片边界 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
如果没有下载就开启一个下载线程
//启动新线程下载downLoadUtils.download(source, path+String.valueOf(source.hashCode()));
第二个重点就是监听下载完成事件,完成下载以后,重新给Textview赋值
这样做了之后,网络图片就可以显示在Textview里面。在网络正常的情况下,如果是相同图片只需要下载一次,这样可以节省了手机的流量。
我还有一种解决方案就是不需要给Textview赋两次值,就是首先解析出来图片路径,然后下载图片,最后赋值给Textview,其实道理是一样的,之前的做法是通过重载方法解析出来图片的路径然后下载图片。只不过是多了一个赋值,没有任何影响。大家有好的思路,也可以介绍下。
转 ---http://www.cnblogs.com/mxgsa/archive/2012/12/20/2823666.html
- Android中Textview显示带html文本-------【HTML标签】
- Android中Textview显示带html文本一-------【HTML标签】
- Android中Textview显示带html文本一-------【HTML标签】
- Android中Textview显示带html文本一-------【HTML标签】
- Android中Textview显示带html文本一-------【HTML标签】
- Android中Textview显示带html文本一-------【HTML标签】
- Android中Textview显示带html文本
- Android中Textview显示带html文本
- Android中Textview显示带html文本二
- Android中Textview显示带html文本三
- Android中Textview显示带html文本…
- Android中Textview显示带html文本…
- Android中Textview显示带html文本…
- Android中用TextVIew显示Html标签文本
- Android中用TextVIew显示Html标签文本
- Android中Textview显示带html文本二-------【Textview显示本地图片】
- Android中Textview显示带html文本二-------【Textview显示本地图片】
- Android中Textview显示带html文本二-------【Textview显示本地图片】
- 博弈
- c#上传并改变图片大小
- Google I/O site
- c#上传大文件
- java web项目不能编译
- Android中Textview显示带html文本-------【HTML标签】
- c#操作excel
- Android源码目录结构
- VC下Unicode 到UTF-8的转换
- 自定义光标移动
- POJ 1039 Pipe
- asp截字符串html
- 内核中的HZ 及延迟等
- Windows下MemCache多端口安装配置