¿Es posible mostrar imágenes en línea desde html en un Android TextView?

Dado el siguiente HTML:

This is text and this is an image .

¿Es posible hacer que la imagen se renderice? Al usar este fragmento: mContentText.setText(Html.fromHtml(text)); , Obtengo una caja cian con bordes negros, lo que me lleva a creer que un TextView tiene una idea de lo que es una etiqueta img.

Si Html.fromHtml(text) un vistazo a la documentación de Html.fromHtml(text) , verás que dice:

Todas las tags en el HTML se mostrarán como una imagen de reemplazo genérica que su progtwig puede luego pasar y reemplazar con imágenes reales.

Si no desea hacer este reemplazo usted mismo puede utilizar el otro método Html.fromHtml() que toma un Html.TagHandler y un Html.ImageGetter como argumentos, así como el texto para analizar.

En su caso, podría analizar null cuanto a Html.TagHandler pero tendría que implementar su propio Html.ImageGetter ya que no hay una implementación predeterminada.

Sin embargo, el problema que tendrá es que Html.ImageGetter necesita ejecutarse de forma síncrona y, si está descargando imágenes de la web, probablemente desee hacerlo de forma asincrónica. Si puede agregar las imágenes que desea mostrar como recursos en su aplicación, su implementación de ImageGetter vuelve mucho más simple. Podrías salir con algo como esto:

 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; } }; 

Sin embargo, es probable que desee averiguar algo más inteligente para mapear cadenas fuente a ID de recursos.

Lo he implementado en mi aplicación, tomado como referencia del pskink .thanx mucho

 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 ImageGetter it contains " + "two images: 
" + "
and
" + ""; String imgs="

\"\"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

"; String src="

\"\"Test Attractions Test Attractions Test Attractions Test Attractions

"; String img="

\"\"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

"; 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 { 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); } } } }

Según el comentario de @rpgmaker a continuación agregué esta respuesta

sí, puedes usar la clase ResolveInfo

compruebe que su archivo sea compatible con las aplicaciones ya instaladas o no

usando el siguiente código:

 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 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; } } 

Esto es lo que uso, que no necesita forzar los nombres de tus recursos y buscar los recursos dibujables primero en tus recursos de aplicaciones y luego en los recursos android en existencia si no se encuentra nada, lo que te permite usar íconos predeterminados y demás.

 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; } } } 

Que se puede usar como tal (ejemplo):

 String myHtml = "This will display an image to the right "; myTextview.setText(Html.fromHtml(myHtml, new ImageGetter(), null); 

Enfrenté el mismo problema y encontré una solución bastante limpia: después de Html.fromHtml () puede ejecutar una AsyncTask que itera sobre todas las tags, busca las imágenes y luego las muestra.

Aquí puede encontrar un código que puede usar (pero necesita cierta personalización): https://gist.github.com/1190397

Utilicé la respuesta de Dave Webb pero la simplifiqué un poco. Siempre y cuando los ID de recursos permanezcan iguales durante el tiempo de ejecución en su caso de uso, no hay realmente una necesidad de escribir su propia clase implementando Html.ImageGetter y perder el tiempo con las cadenas fuente.

Lo que hice fue usar el ID del recurso como una cadena fuente:

 final String img = String.format("", R.drawable.your_image); final String html = String.format("Image: %s", img); 

y usarlo directamente:

 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); 

También puede escribir su propio analizador para extraer la URL de todas las imágenes y luego crear dinámicamente nuevas imágenes y pasar las URL.

Además, si desea realizar el reemplazo usted mismo, el personaje que debe buscar es [].

Pero si usa Eclipse, se volverá loco cuando escriba esa letra en una statement [replace] indicándole que entra en conflicto con Cp1252; este es un error de Eclipse. Para solucionarlo, ve a

Ventana -> Preferencias -> General -> Espacio de trabajo -> Codificación de archivo de texto,

y seleccione [UTF-8]

En caso de que alguien piense que los recursos deben ser declarativos y usar Spannable para múltiples idiomas es un desastre, hice algunas vistas personalizadas

 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 < ![CDATA[Some text  with image in between]]> * assuming there is @drawable/some_image in project files * * Must be accompanied by 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; } } } 

realizar un seguimiento de las actualizaciones, si las hay, en https://gist.github.com/logcat/64234419a935f1effc67