Android實現(xiàn)TextView顯示HTML加圖片的方法
本文實例講述了Android實現(xiàn)TextView顯示HTML加圖片的方法。分享給大家供大家參考,具體如下:
TextView顯示網(wǎng)絡(luò)圖片,我用android2.3的系統(tǒng),可以顯示圖片出來,并且如果圖片比較大,應(yīng)用會卡的現(xiàn)象,肯定是因為使用主線程去獲取網(wǎng)絡(luò)圖片造成的,但如果我用android4.0以上的系統(tǒng)運(yùn)行,則不能顯示圖片,只顯示小方框。
究其原因,是在4.0的系統(tǒng)上執(zhí)行的時候報錯了,異常是:Android.os.NetworkOnMainThreadException 經(jīng)過查文檔,原來是4.0系統(tǒng)不允許主線程(UI線程)訪問網(wǎng)絡(luò),因此導(dǎo)致了其異常。說白了就是在主線程上訪問網(wǎng)絡(luò),會造成主線程掛起,系統(tǒng)不允許使用了。
此處有作部分修改,代碼獨立。圖片實現(xiàn)異步加載。解決上述問題
用法,調(diào)用代碼activity
//TextView 控件 textViewContent = (TextView) getActivity().findViewById(R.id.textview_prodcut_detail_more_zp_content); //HTML文本 zp_content = "測試圖片信息:<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ù)庫技巧總結(jié)》、《Android操作json格式數(shù)據(jù)技巧總結(jié)》、《Android數(shù)據(jù)庫操作技巧總結(jié)》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進(jìn)階教程》、《Android視圖View技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
詳解Android中OkHttp3的例子和在子線程更新UI線程的方法
本篇文章主要介紹了詳解Android中OkHttp3的例子和在子線程更新UI線程的方法 ,非常具有實用價值,需要的朋友可以參考下2017-05-05
Flutter中g(shù)o_router路由管理的使用指南
go_router?是一個?Flutter?的第三方路由插件,相比?Flutter?自帶的路由,go_router?更加靈活,而且簡單易用,下面小編就來和大家聊聊go_router的使用吧2023-08-08
Android?實現(xiàn)自定義圓形進(jìn)度條的三種常用方法
這篇文章主要介紹了Android?實現(xiàn)自定義圓形進(jìn)度條的三種常用方法的相關(guān)資料,需要的朋友可以參考下2023-03-03
Android開發(fā)實現(xiàn)自定義水平滾動的容器示例
這篇文章主要介紹了Android開發(fā)實現(xiàn)自定義水平滾動的容器,涉及Android滾動容器的事件響應(yīng)、屬性運(yùn)算與修改相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Flutter 狀態(tài)管理scoped model源碼解讀
這篇文章主要為大家介紹了Flutter 狀態(tài)管理scoped model源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android中Uri和Path之間的轉(zhuǎn)換的示例代碼
本篇文章主要介紹了Android中Uri和Path之間的轉(zhuǎn)換的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04

