是否有可能在Android TextView中显示来自HTML的内嵌图像?
鉴于以下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>
标签都将显示为一个通用的replace图像,然后您的程序可以通过并replace真实图像。
如果你不想自己做这个replace,你可以使用另一个Html.fromHtml()
方法 ,它需要一个Html.TagHandler
和一个Html.ImageGetter
作为参数以及parsing文本。
在你的情况下,你可以parsingnull
为Html.TagHandler
但是你需要实现你自己的Html.ImageGetter
因为没有默认的实现。
然而,你将遇到的问题是, Html.ImageGetter
需要同步运行,如果你从网上下载图片,你可能会想asynchronous做到这一点。 如果你可以在你的应用程序中添加任何想要显示为资源的图片, 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; } };
你可能想找出更聪明的东西来映射源string资源ID虽然。
我已经在我的应用程序中实现了,从pskink获得了很多的参考
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/assetshttp://img.dovov.comdac_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.auhttp://img.dovov.comcanberra_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);
我面临同样的问题,我find了一个相当干净的解决scheme:Html.fromHtml()后,你可以运行一个AsyncTask遍历所有的标签,获取图像,然后显示它们。
在这里你可以find一些你可以使用的代码(但是它需要一些定制): https : //gist.github.com/1190397
我用戴夫韦伯的答案,但简化了一下。 只要资源ID在你的用例的运行时期间保持不变,就不需要编写你自己的实现Html.ImageGetter
的类,并且处理源string。
我所做的是使用资源ID作为源string:
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);
您也可以编写自己的parsing器来拉取所有图像的URL,然后dynamic创build新的图像浏览并传入url。
另外,如果你想自己做replace,你需要查找的字符是[]。
但是,如果您使用的是Eclipse,那么当您将该字母键入到一个[replace]语句,告诉您它与Cp1252冲突时,它会吓坏了 – 这是一个Eclipse错误。 要修复它,去
窗口 – >首选项 – >常规 – >工作区 – >文本文件编码,
并select[UTF-8]
如果有人认为资源必须声明,并使用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