Android中Textview显示带html文本【Textview显示本地图片】

Textview可以显示基本的HTML标签

<a href="...">
<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>

下面着重说一下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线程)访问网络,因此导致了其异常。说白了就是在主线程上访问网络,会造成主线程挂起,系统不允许使用了。

看到Android4.0不允许主线程(UI线程)访问网络,立马脑子就想起来 ,不能用主线程访问,可以开另外一个线程,把图片下到本地sd卡中,之后在赋值到TextView里面。不急着来代码,我和大家在把这个逻辑在理一下:获取图片路径——异步下载图片——完成下载后重新赋值Textview


下面是Activity页面处理代码:

private TextView tView;
    private DownLoadUtils downLoadUtils;
    //保存文件路径
    private final String path="/mnt/sdcard/downimg";
    //设置text的值
    String sText = "测试图片信息:<br><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" />";
    @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() {
        //初始化下载类
        downLoadUtils=new DownLoadUtils();
        //设置下载类监听事件
        downLoadUtils.setOnDownloadListener(onDownloadListener);
        //给Textview赋值
        tView.setText(Html.fromHtml(sText, imageGetter, null));
    }
    final Html.ImageGetter imageGetter = new Html.ImageGetter() {
        public Drawable getDrawable(String source) {
            Drawable drawable = null;
            String fileString=path+String.valueOf(source.hashCode());
            Log.i("DEBUG", fileString+"");
            Log.i("DEBUG", source+"");
            //判断SD卡里面是否存在图片文件
            if (new File(fileString).exists()) {
                Log.i("DEBUG", fileString+"  eixts");
                //获取本地文件返回Drawable
                drawable=Drawable.createFromPath(fileString);
                //设置图片边界
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
                return drawable;
            }else {
                Log.i("DEBUG", fileString+" Do not eixts");
                //启动新线程下载
                downLoadUtils.download(source, path+String.valueOf(source.hashCode()));
                return drawable;
            }
            
        };
    };
    OnDownloadListener onDownloadListener=new OnDownloadListener() {
        
        //下载进度
        public void onDownloadUpdate(DownLoadUtils manager, int percent) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", percent+"");
        }
        
        //下载失败
        public void onDownloadError(DownLoadUtils manager, Exception e) {
            // TODO Auto-generated method stub
            
        }
        
        //开始下载
        public void onDownloadConnect(DownLoadUtils manager) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", "Start  //////");
        }
        
        //完成下载
        public void onDownloadComplete(DownLoadUtils manager, Object result) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", result.toString());
            //替换sTExt的值,就是把图片的网络路径换成本地SD卡图片路径(最早想法,可以不需要这样做了)
            //sText.replace(result.toString(), path+String.valueOf(result.hashCode()));
            //再一次赋值给Textview
            tView.setText(Html.fromHtml(sText, imageGetter, null));
        }
    };

下面来简单的介绍下上面的代码,最重要的就是有两点,就是第一次把sText赋值Textview,在Html.ImageGetter的重载方法里面去判断该图片文件是否已经下载,如果已经下载,就直接读取SD卡里面的图片文件

    //获取本地文件返回Drawable
    drawable=Drawable.createFromPath(fileString);                //设置图片边界
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

如果没有下载就开启一个下载线程

    downLoadUtils.download(source, path+String.valueOf(source.hashCode()));

第二个重点就是监听下载完成事件,完成下载以后,重新给Textview赋值

OnDownloadListener onDownloadListener=new OnDownloadListener() {
        
        //下载进度
        public void onDownloadUpdate(DownLoadUtils manager, int percent) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", percent+"");
        }
        
        //下载失败
        public void onDownloadError(DownLoadUtils manager, Exception e) {
            // TODO Auto-generated method stub
            
        }
        
        //开始下载
        public void onDownloadConnect(DownLoadUtils manager) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", "Start  //////");
        }
        
        //完成下载
        public void onDownloadComplete(DownLoadUtils manager, Object result) {
            // TODO Auto-generated method stub
            Log.i("DEBUG", result.toString());
            //替换sTExt的值,就是把图片的网络路径换成本地SD卡图片路径(最早想法,可以不需要这样做了)
            //sText.replace(result.toString(), path+String.valueOf(result.hashCode()));
            //再一次赋值给Textview
            tView.setText(Html.fromHtml(sText, imageGetter, null));
        }
    };

这样做了之后,网络图片就可以显示在Textview里面。在网络正常的情况下,如果是相同图片只需要下载一次,这样可以节省了手机的流量。

我还有一种解决方案就是不需要给Textview赋两次值,就是首先解析出来图片路径,然后下载图片,最后赋值给Textview,其实道理是一样的,之前的做法是通过重载方法解析出来图片的路径然后下载图片。只不过是多了一个赋值,没有任何影响。大家有好的思路,也可以介绍下。

时间: 2024-11-01 16:05:40

Android中Textview显示带html文本【Textview显示本地图片】的相关文章

Android定制控件-带图像的TextView

最近在学习Android,边看书边敲代码,看到是李宁的Android开发完全讲义,因为是对着书本敲的, 所以代码跟原书的代码基本上是一致的 看到第四章,定制控件,觉得需要记录下些东西,所有把代码写到博客作为自己以后查阅的资料. 先上效果图 在src新建net.blogjava.mobile.widget/IconTextView.java 代码如下: package net.blogjava.mobile.widget; import android.content.Context; impor

Android中通过反射来设置Toast的显示时间

这个Toast的显示在Android中的用途还是非常大的,同一时候我们也知道toast显示的时间是不可控的.我们仅仅能改动他的显示样式和显示的位置,尽管他提供了一个显示时间的设置方法.可是那是没有效果的(后面会说到).他有两个静态的常量Toast.SHORT和Toast.LONG,这个在后面我会在源码中看到这个两个时间事实上是2.5s和3s. 那么我们假设真想控制toast的显示时间该怎么办呢?真的是无计可施了吗?天无绝人之路,并且Linux之父以前说过:遇到问题就去看那个操蛋的源码吧.!以下就

在Android中使用自带API操作Json

Json简介 JavaScript对象表示法(JavaScript Object Notation) 是存储和交换文本信息的语法 特点 是轻量级的文本数据交换格式 独立于语言和平台 具有自我描述性,更易理解 Json与XML 类似XML,比XML更小.更快.更易解析 没有结束标签 更短 读写的速度更快 使用数组 不使用保留字 Json语法 是JavaScript对象表示法语法的子集 数组在键值对中 数据由逗号分隔 大括号保存对象 中括号保存数组 Json值可以是 数字(整数或浮点数) 字符串(在

在Android中Intent的概念及应用(一)——显示Intent和隐式Intent

Intent寻找目标组件的两种方式: 显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的. 隐式Intent:通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间. 一.显示Intent: 创建一个Activity的完整过程: 1.手动创建一个类,让其继承自Activity: public class MyAty extends Activity 2.让其绑定一个

Android中CleanEditText自动带X号输入框的EditText

图标在这里.你懂得 实现的效果如下: 今天做项目遇到的问题.记录下.自动带删除按钮的EditText. public class CleanEditText extends EditText implements OnFocusChangeListener, TextWatcher { /** * 删除按钮的引用 */ private Drawable mClearDrawable; public CleanEditText(Context context) { this(context, nu

(转)Android中系统自带的锁:WalkLock、KeyguardLock

Android系统自带了两把锁: (1)WalkLock:唤醒锁,点亮屏幕用的 ; (2)KeyguardLock:键盘锁,解锁键盘用的; WalkLock 唤醒锁 (1)WalkLock真的能点亮屏幕吗? 答案是肯定的,可是有时候为什么不点亮屏幕,这个就是参数设置的问题了. PowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "Gank"); PowerM

Android中新建的文件在R没有显示相应的文件解决的方法总结

我们有时会发现当我们新建一个文件或者目录在Generated Java Files(gen)文件的R.java中没有生成相应的静态类或者静态属性.此时你可能出现了以下的情况.注意參照解决. 一般正常情况R文件都是会自己主动更新的.不能更新的,请检測文件的格式.以图图片为例.似乎android仅仅支持jpg和png格式的图片.这个不太清楚,或者你的图片的名字有汉字或者你的图片的名字有大写字母这些都是不行的. 例如以下的图片格式就是非法的.所以R文件不能自己主动更新 图片1.png //图片不能汉字

android中使用Http下载文件并保存到本地SD卡

---恢复内容开始--- 1.AndroidMainfest.xml中设置权限 1 <uses-permission android:name="android.permission.INTERNET"></uses-permission> 2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission

Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据

2014-06-11 10:45:14   阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何转换为Bitmap呢? 由于得到的数据是unsigned char *类型的数据,而对于Bitmap的类来说,其类方法里面: 1 2 public static Bitmap createBitmap(int colors[], int offset, int stride,             int width, int height, Config config) 要求传