Android實(shí)現(xiàn)TextView顯示HTML加圖片的方法
本文實(shí)例講述了Android實(shí)現(xiàn)TextView顯示HTML加圖片的方法。分享給大家供大家參考,具體如下:
TextView顯示網(wǎng)絡(luò)圖片,我用android2.3的系統(tǒng),可以顯示圖片出來,并且如果圖片比較大,應(yīng)用會(huì)卡的現(xiàn)象,肯定是因?yàn)槭褂弥骶€程去獲取網(wǎng)絡(luò)圖片造成的,但如果我用android4.0以上的系統(tǒng)運(yùn)行,則不能顯示圖片,只顯示小方框。
究其原因,是在4.0的系統(tǒng)上執(zhí)行的時(shí)候報(bào)錯(cuò)了,異常是:Android.os.NetworkOnMainThreadException 經(jīng)過查文檔,原來是4.0系統(tǒng)不允許主線程(UI線程)訪問網(wǎng)絡(luò),因此導(dǎo)致了其異常。說白了就是在主線程上訪問網(wǎng)絡(luò),會(huì)造成主線程掛起,系統(tǒng)不允許使用了。
此處有作部分修改,代碼獨(dú)立。圖片實(shí)現(xiàn)異步加載。解決上述問題
用法,調(diào)用代碼activity
//TextView 控件 textViewContent = (TextView) getActivity().findViewById(R.id.textview_prodcut_detail_more_zp_content); //HTML文本 zp_content = "測(cè)試圖片信息:<br><img src=\"http://b2c.zeeeda.com/upload/2013/05/10/136814766742544.jpg\" />"; //默認(rèn)圖片,無圖片或沒加載完顯示此圖片 Drawable defaultDrawable = MainActivity.ma.getResources().getDrawable(R.drawable.stub); //調(diào)用 Spanned sp = Html.fromHtml(zp_content, new HtmlImageGetter(textViewContent, "/esun_msg", defaultDrawable), null); textViewContent.setText(sp);
HtmlImageGetter類:
import java.io.InputStream; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Environment; import android.text.Html.ImageGetter; import android.util.Log; import android.widget.TextView; public class HtmlImageGetter implements ImageGetter{ private TextView _htmlText; private String _imgPath; private Drawable _defaultDrawable; private String TAG = "HtmlImageGetter"; public HtmlImageGetter(TextView htmlText, String imgPath, Drawable defaultDrawable){ _htmlText = htmlText; _imgPath = imgPath; _defaultDrawable = defaultDrawable; } @Override public Drawable getDrawable(String imgUrl) { String imgKey = String.valueOf(imgUrl.hashCode()); String path = Environment.getExternalStorageDirectory() + _imgPath; FileUtil.createPath(path); String[] ss = imgUrl.split("\\."); String imgX = ss[ss.length-1]; imgKey = path+"/" + imgKey+"."+imgX; if(FileUtil.exists(imgKey)){ Drawable drawable = FileUtil.getImageDrawable(imgKey); if(drawable != null){ drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); return drawable; }else{ Log.v(TAG,"load img:"+imgKey+":null"); } } URLDrawable urlDrawable = new URLDrawable(_defaultDrawable); new AsyncThread(urlDrawable).execute(imgKey, imgUrl); return urlDrawable; } private class AsyncThread extends AsyncTask<String, Integer, Drawable> { private String imgKey; private URLDrawable _drawable; public AsyncThread(URLDrawable drawable){ _drawable = drawable; } @Override protected Drawable doInBackground(String... strings) { imgKey = strings[0]; InputStream inps = NetWork.getInputStream(strings[1]); if(inps == null) return _drawable; FileUtil.saveFile(imgKey, inps); Drawable drawable = Drawable.createFromPath(imgKey); return drawable; } public void onProgressUpdate(Integer... value) { } @Override protected void onPostExecute(Drawable result) { _drawable.setDrawable(result); _htmlText.setText(_htmlText.getText()); } } public class URLDrawable extends BitmapDrawable { private Drawable drawable; public URLDrawable(Drawable defaultDraw){ setDrawable(defaultDraw); } private void setDrawable(Drawable ndrawable){ drawable = ndrawable; drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable .getIntrinsicHeight()); setBounds(0, 0, drawable.getIntrinsicWidth(), drawable .getIntrinsicHeight()); } @Override public void draw(Canvas canvas) { drawable.draw(canvas); } } }
NetWork 類:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.entity.BufferedHttpEntity; import org.apache.http.impl.client.DefaultHttpClient; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; public class NetWork { private static String TAG = "NetWork"; public static String getHttpData(String baseUrl){ return getHttpData(baseUrl, "GET", "", null); } public static String postHttpData(String baseUrl, String reqData){ return getHttpData(baseUrl, "POST", reqData, null); } public static String postHttpData(String baseUrl, String reqData, HashMap<String, String> propertys){ return getHttpData(baseUrl, "POST", reqData, propertys); } /** * 獲取賽事信息 * @return */ public static String getHttpData(String baseUrl, String method, String reqData, HashMap<String, String> propertys){ String data = "", str; PrintWriter outWrite = null; InputStream inpStream = null; BufferedReader reader = null; HttpURLConnection urlConn = null; try{ URL url = new URL(baseUrl); urlConn = (HttpURLConnection)url.openConnection(); //啟用gzip壓縮 urlConn.addRequestProperty("Accept-Encoding", "gzip, deflate"); urlConn.setRequestMethod(method); urlConn.setDoOutput(true); urlConn.setConnectTimeout(3000); if(propertys != null && !propertys.isEmpty()){ Iterator<Map.Entry<String, String>> props = propertys.entrySet().iterator(); Map.Entry<String, String> entry; while (props.hasNext()){ entry = props.next(); urlConn.setRequestProperty(entry.getKey(), entry.getValue()); } } outWrite = new PrintWriter(urlConn.getOutputStream()); outWrite.print(reqData); outWrite.flush(); urlConn.connect(); //獲取數(shù)據(jù)流 inpStream = urlConn.getInputStream(); String encode = urlConn.getHeaderField("Content-Encoding"); //如果通過gzip if(encode !=null && encode.indexOf("gzip") != -1){ Log.v(TAG, "get data :" + encode); inpStream = new GZIPInputStream(inpStream); }else if(encode != null && encode.indexOf("deflate") != -1){ inpStream = new InflaterInputStream(inpStream); } reader = new BufferedReader(new InputStreamReader(inpStream)); while((str = reader.readLine()) != null){ data += str; } }catch (MalformedURLException ex){ ex.printStackTrace(); }catch (IOException ex){ ex.printStackTrace(); }finally{ if(reader !=null && urlConn!=null){ try { outWrite.close(); inpStream.close(); reader.close(); urlConn.disconnect(); } catch (IOException ex) { ex.printStackTrace(); } } } Log.d(TAG, "[Http data]["+baseUrl+"]:" + data); return data; } /** * 獲取Image信息 * @return */ public static Bitmap getBitmapData(String imgUrl){ Bitmap bmp = null; Log.d(TAG, "get imgage:"+imgUrl); InputStream inpStream = null; try{ HttpGet http = new HttpGet(imgUrl); HttpClient client = new DefaultHttpClient(); HttpResponse response = (HttpResponse)client.execute(http); HttpEntity httpEntity = response.getEntity(); BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpEntity); //獲取數(shù)據(jù)流 inpStream = bufferedHttpEntity.getContent(); bmp = BitmapFactory.decodeStream(inpStream); }catch (Exception ex){ ex.printStackTrace(); }finally{ if(inpStream !=null){ try { inpStream.close(); } catch (IOException ex) { ex.printStackTrace(); } } } return bmp; } /** * 獲取url的InputStream * @param urlStr * @return */ public static InputStream getInputStream(String urlStr){ Log.d(TAG, "get http input:"+urlStr); InputStream inpStream = null; try{ HttpGet http = new HttpGet(urlStr); HttpClient client = new DefaultHttpClient(); HttpResponse response = (HttpResponse)client.execute(http); HttpEntity httpEntity = response.getEntity(); BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpEntity); //獲取數(shù)據(jù)流 inpStream = bufferedHttpEntity.getContent(); }catch (Exception ex){ ex.printStackTrace(); }finally{ if(inpStream !=null){ try { inpStream.close(); } catch (IOException ex) { ex.printStackTrace(); } } } return inpStream; } }
FileUtil類:
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Environment; import android.util.Log; public class FileUtil { private static int FILE_SIZE = 4*1024; private static String TAG = "FileUtil"; public static boolean hasSdcard(){ String status = Environment.getExternalStorageState(); if(status.equals(Environment.MEDIA_MOUNTED)){ return true; } return false; } public static boolean createPath(String path){ File f = new File(path); if(!f.exists()){ Boolean o = f.mkdirs(); Log.i(TAG, "create dir:"+path+":"+o.toString()); return o; } return true; } public static boolean exists(String file){ return new File(file).exists(); } public static File saveFile(String file, InputStream inputStream){ File f = null; OutputStream outSm = null; try{ f = new File(file); String path = f.getParent(); if(!createPath(path)){ Log.e(TAG, "can't create dir:"+path); return null; } if(!f.exists()){ f.createNewFile(); } outSm = new FileOutputStream(f); byte[] buffer = new byte[FILE_SIZE]; while((inputStream.read(buffer)) != -1){ outSm.write(buffer); } outSm.flush(); }catch (IOException ex) { ex.printStackTrace(); return null; }finally{ try{ if(outSm != null) outSm.close(); }catch (IOException ex) { ex.printStackTrace(); } } Log.v(TAG,"[FileUtil]save file:"+file+":"+Boolean.toString(f.exists())); return f; } public static Drawable getImageDrawable(String file){ if(!exists(file)) return null; try{ InputStream inp = new FileInputStream(new File(file)); return BitmapDrawable.createFromStream(inp, "img"); }catch (Exception ex){ ex.printStackTrace(); } return null; } }
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android資源操作技巧匯總》、《Android文件操作技巧匯總》、《Android操作SQLite數(shù)據(jù)庫(kù)技巧總結(jié)》、《Android操作json格式數(shù)據(jù)技巧總結(jié)》、《Android數(shù)據(jù)庫(kù)操作技巧總結(jié)》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進(jìn)階教程》、《Android視圖View技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
相關(guān)文章
Android實(shí)現(xiàn)快遞物流時(shí)間軸效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)快遞物流時(shí)間軸效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android實(shí)現(xiàn)左側(cè)滑動(dòng)菜單
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)左側(cè)滑動(dòng)菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02詳解Android中OkHttp3的例子和在子線程更新UI線程的方法
本篇文章主要介紹了詳解Android中OkHttp3的例子和在子線程更新UI線程的方法 ,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05Flutter中g(shù)o_router路由管理的使用指南
go_router?是一個(gè)?Flutter?的第三方路由插件,相比?Flutter?自帶的路由,go_router?更加靈活,而且簡(jiǎn)單易用,下面小編就來和大家聊聊go_router的使用吧2023-08-08Android?實(shí)現(xiàn)自定義圓形進(jìn)度條的三種常用方法
這篇文章主要介紹了Android?實(shí)現(xiàn)自定義圓形進(jìn)度條的三種常用方法的相關(guān)資料,需要的朋友可以參考下2023-03-03Android開發(fā)實(shí)現(xiàn)自定義水平滾動(dòng)的容器示例
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)自定義水平滾動(dòng)的容器,涉及Android滾動(dòng)容器的事件響應(yīng)、屬性運(yùn)算與修改相關(guān)操作技巧,需要的朋友可以參考下2017-10-10Flutter 狀態(tài)管理scoped model源碼解讀
這篇文章主要為大家介紹了Flutter 狀態(tài)管理scoped model源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android中Uri和Path之間的轉(zhuǎn)換的示例代碼
本篇文章主要介紹了Android中Uri和Path之間的轉(zhuǎn)換的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04