Android中Textview顯示帶html文本【Textview顯示本地圖片】

Textview能夠顯示基本的HTML標籤java

<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)方法,獲取該路徑的圖片。android

例如:網絡

final Html.ImageGetter imageGetter = new Html.ImageGetter() {        
    public Drawable getDrawable(String source) {            
        return drawable;
    };
};

下面來講下public Drawable getDrawable(String source)這個方法,source就是圖片路徑!異步

例如:ide

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=路徑/> 這個路徑既能夠是網絡圖片,也能夠本地圖片,項目資源圖片url

例如:本地圖片<img src=\""/sdcard/images/test.jpg"\"/>   項目資源圖片 <img src=\""+R.drawable.market_none_image+"\"/>spa

可是不一樣的路徑,ImageGetter的重載處理方法都不同,下面來一一介紹各類的處理方式.線程

第一種:本地圖片code

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,其實道理是同樣的,以前的作法是經過重載方法解析出來圖片的路徑而後下載圖片。只不過是多了一個賦值,沒有任何影響。你們有好的思路,也能夠介紹下。

相關文章
相關標籤/搜索