[英]Is it possible to display inline images from html in an Android TextView?
鑒於以下 HTML:
<p>This is text and this is an image <img src="http://www.example.com/image.jpg" />.</p>
是否可以使圖像渲染? 使用此代碼段時: mContentText.setText(Html.fromHtml(text));
,我得到一個帶有黑色邊框的青色框,讓我相信 TextView 對 img 標簽是什么有所了解。
如果您查看Html.fromHtml(text)
的文檔,您會看到它說:
HTML 中的任何
<img>
標記都將顯示為通用替換圖像,然后您的程序可以通過該圖像替換為真實圖像。
如果您不想自己進行此替換,則可以使用其他Html.fromHtml()
方法,該方法將Html.TagHandler
和Html.ImageGetter
作為參數以及要解析的文本。
在您的情況下,您可以像Html.TagHandler
一樣解析null
,但您需要實現自己的Html.ImageGetter
因為沒有默認實現。
但是,您將遇到的問題是Html.ImageGetter
需要同步運行,如果您從 Web 下載圖像,您可能希望異步執行此操作。 如果您可以在應用程序中添加任何要顯示為資源的圖像,那么您的ImageGetter
實現將變得更加簡單。 你可以逃脫類似的事情:
private class ImageGetter implements Html.ImageGetter {
public Drawable getDrawable(String source) {
int id;
if (source.equals("stack.jpg")) {
id = R.drawable.stack;
}
else if (source.equals("overflow.jpg")) {
id = R.drawable.overflow;
}
else {
return null;
}
Drawable d = getResources().getDrawable(id);
d.setBounds(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight());
return d;
}
};
不過,您可能想找出更智能的方法將源字符串映射到資源 ID。
我已經在我的應用程序中實現了,從pskink .thanx 中獲取了很多參考
package com.example.htmltagimg;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.text.Html.ImageGetter;
import android.text.Spanned;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends Activity implements ImageGetter {
private final static String TAG = "TestImageGetter";
private TextView mTv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String source = "this is a test of <b>ImageGetter</b> it contains " +
"two images: <br/>" +
"<img src=\"http://developer.android.com/assets/images/dac_logo.png\"><br/>and<br/>" +
"<img src=\"http://www.hdwallpapersimages.com/wp-content/uploads/2014/01/Winter-Tiger-Wild-Cat-Images.jpg\">";
String imgs="<p><img alt=\"\" src=\"http://images.visitcanberra.com.au/images/canberra_hero_image.jpg\" style=\"height:50px; width:100px\" />Test Article, Test Article, Test Article, Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,v</p>";
String src="<p><img alt=\"\" src=\"http://stylonica.com/wp-content/uploads/2014/02/Beauty-of-nature-random-4884759-1280-800.jpg\" />Test Attractions Test Attractions Test Attractions Test Attractions</p>";
String img="<p><img alt=\"\" src=\"/site_media/photos/gallery/75b3fb14-3be6-4d14-88fd-1b9d979e716f.jpg\" style=\"height:508px; width:640px\" />Test Article, Test Article, Test Article, Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,Test Article,v</p>";
Spanned spanned = Html.fromHtml(imgs, this, null);
mTv = (TextView) findViewById(R.id.text);
mTv.setText(spanned);
}
@Override
public Drawable getDrawable(String source) {
LevelListDrawable d = new LevelListDrawable();
Drawable empty = getResources().getDrawable(R.drawable.ic_launcher);
d.addLevel(0, 0, empty);
d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());
new LoadImage().execute(source, d);
return d;
}
class LoadImage extends AsyncTask<Object, Void, Bitmap> {
private LevelListDrawable mDrawable;
@Override
protected Bitmap doInBackground(Object... params) {
String source = (String) params[0];
mDrawable = (LevelListDrawable) params[1];
Log.d(TAG, "doInBackground " + source);
try {
InputStream is = new URL(source).openStream();
return BitmapFactory.decodeStream(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
Log.d(TAG, "onPostExecute drawable " + mDrawable);
Log.d(TAG, "onPostExecute bitmap " + bitmap);
if (bitmap != null) {
BitmapDrawable d = new BitmapDrawable(bitmap);
mDrawable.addLevel(1, 1, d);
mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
mDrawable.setLevel(1);
// i don't know yet a better way to refresh TextView
// mTv.invalidate() doesn't work as expected
CharSequence t = mTv.getText();
mTv.setText(t);
}
}
}
}
根據下面@rpgmaker評論,我添加了這個答案
是的,您可以使用ResolveInfo類
檢查已安裝的應用程序是否支持您的文件
使用以下代碼:
private boolean isSupportedFile(File file) throws PackageManager.NameNotFoundException {
PackageManager pm = mContext.getPackageManager();
java.io.File mFile = new java.io.File(file.getFileName());
Uri data = Uri.fromFile(mFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(data, file.getMimeType());
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfos != null && resolveInfos.size() > 0) {
Drawable icon = mContext.getPackageManager().getApplicationIcon(resolveInfos.get(0).activityInfo.packageName);
Glide.with(mContext).load("").placeholder(icon).into(binding.fileAvatar);
return true;
} else {
Glide.with(mContext).load("").placeholder(R.drawable.avatar_defaultworkspace).into(binding.fileAvatar);
return false;
}
}
這就是我使用的,它不需要您對資源名稱進行硬核,並且會首先在您的應用程序資源中查找可繪制資源,然后在未找到任何內容的情況下在庫存 android 資源中查找 - 允許您使用默認圖標等。
private class ImageGetter implements Html.ImageGetter {
public Drawable getDrawable(String source) {
int id;
id = getResources().getIdentifier(source, "drawable", getPackageName());
if (id == 0) {
// the drawable resource wasn't found in our package, maybe it is a stock android drawable?
id = getResources().getIdentifier(source, "drawable", "android");
}
if (id == 0) {
// prevent a crash if the resource still can't be found
return null;
}
else {
Drawable d = getResources().getDrawable(id);
d.setBounds(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight());
return d;
}
}
}
可以這樣使用(示例):
String myHtml = "This will display an image to the right <img src='ic_menu_more' />";
myTextview.setText(Html.fromHtml(myHtml, new ImageGetter(), null);
我遇到了同樣的問題,我找到了一個非常干凈的解決方案:在 Html.fromHtml() 之后,您可以運行一個 AsyncTask 迭代所有標簽,獲取圖像然后顯示它們。
在這里你可以找到一些你可以使用的代碼(但它需要一些自定義): https : //gist.github.com/1190397
我使用了 Dave Webb 的答案,但對其進行了一些簡化。 只要資源 ID 在您的用例中在運行時保持不變,就沒有必要編寫自己的類來實現Html.ImageGetter
並弄亂源字符串。
我所做的是使用資源 ID 作為源字符串:
final String img = String.format("<img src=\"%s\"/>", R.drawable.your_image);
final String html = String.format("Image: %s", img);
並直接使用它:
Html.fromHtml(html, new Html.ImageGetter() {
@Override
public Drawable getDrawable(final String source) {
Drawable d = null;
try {
d = getResources().getDrawable(Integer.parseInt(source));
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
} catch (Resources.NotFoundException e) {
Log.e("log_tag", "Image not found. Check the ID.", e);
} catch (NumberFormatException e) {
Log.e("log_tag", "Source string not a valid resource ID.", e);
}
return d;
}
}, null);
科特林
也有可能使用sufficientlysecure.htmltextview.HtmlTextView
在 gradle 文件中使用如下:
項目gradle文件:
repositories {
jcenter()
}
應用程序gradle文件:
dependencies {
implementation 'org.sufficientlysecure:html-textview:3.9'
}
在 xml 文件中,將您的 textView 替換為:
<org.sufficientlysecure.htmltextview.HtmlTextView
android:id="@+id/allNewsBlockTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:textColor="#000"
android:textSize="18sp"
app:htmlToString="@{detailsViewModel.selectedText}" />
上面的最后一行是如果您使用綁定適配器,代碼將如下所示:
@BindingAdapter("htmlToString")
fun bindTextViewHtml(textView: HtmlTextView, htmlValue: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setHtml(
htmlValue,
HtmlHttpImageGetter(textView, "n", true)
);
} else {
textView.setHtml(
htmlValue,
HtmlHttpImageGetter(textView, "n", true)
);
}
}
來自 github頁面的更多信息,非常感謝作者!!!!!!
另外,如果您確實想自己進行替換,則需要查找的字符是 [  ]。
但是,如果您使用 Eclipse,當您將該字母輸入到 [replace] 語句中時,它會嚇壞您,告訴您它與 Cp1252 沖突 - 這是一個 Eclipse 錯誤。 要修復它,請轉到
窗口 -> 首選項 -> 常規 -> 工作區 -> 文本文件編碼,
並選擇[UTF-8]
您還可以編寫自己的解析器來提取所有圖像的 URL,然后動態創建新的圖像視圖並傳入 url。
如果有人認為資源必須是聲明性的並且對多種語言使用 Spannable 是一團糟,我做了一些自定義視圖
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.Html.ImageGetter;
import android.text.Spanned;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* XXX does not support android:drawable, only current app packaged icons
*
* Use it with strings like <string name="text"><![CDATA[Some text <img src="some_image"></img> with image in between]]></string>
* assuming there is @drawable/some_image in project files
*
* Must be accompanied by styleable
* <declare-styleable name="HtmlTextView">
* <attr name="android:text" />
* </declare-styleable>
*/
public class HtmlTextView extends TextView {
public HtmlTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HtmlTextView);
String html = context.getResources().getString(typedArray.getResourceId(R.styleable.HtmlTextView_android_text, 0));
typedArray.recycle();
Spanned spannedFromHtml = Html.fromHtml(html, new DrawableImageGetter(), null);
setText(spannedFromHtml);
}
private class DrawableImageGetter implements ImageGetter {
@Override
public Drawable getDrawable(String source) {
Resources res = getResources();
int drawableId = res.getIdentifier(source, "drawable", getContext().getPackageName());
Drawable drawable = res.getDrawable(drawableId, getContext().getTheme());
int size = (int) getTextSize();
int width = size;
int height = size;
// int width = drawable.getIntrinsicWidth();
// int height = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, width, height);
return drawable;
}
}
}
跟蹤更新(如果有),請訪問https://gist.github.com/logcat/64234419a935f1effc67
我使用下面的代碼並為我工作加載HTMl
和<img>
標簽在 Android TextView
使用Html.ImageGetter
和AsyncTask
:
String text = your html code;
Spanned spanned = Html.fromHtml(text,
new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
LevelListDrawable d = new LevelListDrawable();
Drawable empty = getResources().getDrawable(R.drawable.abc_btn_check_material);
;
d.addLevel(0, 0, empty);
d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());
new ImageGetterAsyncTask(yourActivity.this, source, d).execute(binding.yourTextView);
return d;
}
}, new MyHtmlTagHandler());
binding.yourTextView.setText(spanned);
然后你應該將這個 AsyncTask class 添加到你的代碼中以加載圖像:
class ImageGetterAsyncTask extends AsyncTask<TextView, Void, Bitmap> {
private LevelListDrawable levelListDrawable;
private Context context;
private String source;
private TextView t;
public ImageGetterAsyncTask(Context context, String source, LevelListDrawable levelListDrawable) {
this.context = context;
this.source = source;
this.levelListDrawable = levelListDrawable;
}
@Override
protected Bitmap doInBackground(TextView... params) {
t = params[0];
try {
Log.d(TAG, "Downloading the image from: " + source);
return Picasso.with(context).load(source).get();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onPostExecute(final Bitmap bitmap) {
try {
Drawable d = new BitmapDrawable(context.getResources(), bitmap);
Point size = new Point();
((Activity) context).getWindowManager().getDefaultDisplay().getSize(size);
// Lets calculate the ratio according to the screen width in px
int multiplier = size.x / bitmap.getWidth();
Log.d(TAG, "multiplier: " + multiplier);
levelListDrawable.addLevel(1, 1, d);
// Set bounds width and height according to the bitmap resized size
levelListDrawable.setBounds(0, 0, bitmap.getWidth() * multiplier, bitmap.getHeight() * multiplier);
levelListDrawable.setLevel(1);
t.setText(t.getText()); // invalidate() doesn't work correctly...
} catch (Exception e) { /* Like a null bitmap, etc. */ }
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.