Est-il possible d'afficher des images en ligne à partir de html dans un TextView Android?

Compte tenu du HTML suivant:

<p>This is text and this is an image <img src="http://www.example.com/image.jpg" />.</p>

Est-il possible de réaliser l'image? Lorsque vous utilisez cet extrait: mContentText.setText(Html.fromHtml(text)); , Je reçois une boîte cyan avec des bordures noires, ce qui me fait croire qu'un TextView a une idée de ce qu'est une étiquette img.

8 Solutions collect form web for “Est-il possible d'afficher des images en ligne à partir de html dans un TextView Android?”

Si vous consultez la documentation de Html.fromHtml(text) vous verrez que cela indique:

Toutes les étiquettes <img> dans le HTML s'affichent comme une image de remplacement générique que votre programme peut alors passer et remplacer par des images réelles.

Si vous ne souhaitez pas vous substituer vous-même, vous pouvez utiliser l'autre méthode Html.fromHtml() qui prend un Html.TagHandler et un Html.ImageGetter comme arguments ainsi que le texte à analyser.

Dans votre cas, vous pouvez analyser null comme pour Html.TagHandler mais vous devriez implémenter votre propre Html.ImageGetter car il n'y a pas de mise en œuvre par défaut.

Cependant, le problème que vous allez est que le Html.ImageGetter doit fonctionner de manière synchrone et si vous téléchargez des images depuis le Web, vous voudrez probablement le faire de manière asynchrone. Si vous pouvez ajouter des images que vous souhaitez afficher en tant que ressources dans votre application, votre application ImageGetter devient beaucoup plus simple. Vous pouvez sortir avec quelque chose comme:

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

Vous voudrez probablement trouver quelque chose de plus intelligent pour le mappage des chaînes source aux identifiants de ressources.

J'ai mis en œuvre dans mon application, pris part du pskink .thanx beaucoup

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

Selon le commentaire @rpgmaker ci-dessous, j'ai ajouté cette réponse

Oui, vous pouvez le faire en utilisant la classe ResolveInfo

Vérifiez que votre fichier est pris en charge avec des applications déjà installées ou non

En utilisant le code ci-dessous:

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

C'est ce que j'utilise, ce qui ne vous oblige pas à endommager vos noms de ressources et à chercher les ressources étirables d'abord dans les ressources de vos applications, puis dans les ressources de stock android si rien n'a été trouvé – vous permettant d'utiliser des icônes par défaut et autres.

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

Ce qui peut être utilisé comme tel (exemple):

 String myHtml = "This will display an image to the right <img src='ic_menu_more' />"; myTextview.setText(Html.fromHtml(myHtml, new ImageGetter(), null); 

J'ai fait face au même problème et j'ai trouvé une solution assez propre: après Html.fromHtml (), vous pouvez exécuter un AsyncTask qui itère sur toutes les balises, récupère les images puis les affiche.

Ici, vous pouvez trouver un code que vous pouvez utiliser (mais il faut une certaine personnalisation): https://gist.github.com/1190397

J'ai utilisé la réponse de Dave Webb, mais je l'ai simplifié un peu. Tant que les identifiants de ressources resteront identiques pendant le temps d'exécution dans votre cas d'utilisation, il n'est pas nécessaire d'écrire votre propre classe en mettant en œuvre Html.ImageGetter et vous déranger avec des sources.

Ce que j'ai fait, c'était l'ID de la ressource comme source-string:

 final String img = String.format("<img src=\"%s\"/>", R.drawable.your_image); final String html = String.format("Image: %s", img); 

Et l'utiliser directement:

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

Vous pouvez également écrire votre propre analyseur pour extraire l'URL de toutes les images, puis créer dynamiquement de nouvelles images et passer les URL.

En outre, si vous voulez faire le remplacement vous-même, le caractère que vous devez rechercher est [].

Mais si vous utilisez Eclipse, cela vous dérangera lorsque vous tapez cette lettre dans une déclaration [replace] vous indiquant qu'elle est en conflit avec Cp1252 – il s'agit d'un bug Eclipse. Pour le réparer, allez à

Fenêtre -> Préférences -> Général -> Espace de travail -> Codage de fichier texte,

Et sélectionnez [UTF-8]

Dans le cas où quelqu'un pense que les ressources doivent être déclaratives et utiliser Spannable pour plusieurs langues est un désordre, j'ai fait une vue personnalisée

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

Suivre les mises à jour, le cas échéant, à l' adresse https://gist.github.com/logcat/64234419a935f1effc67

coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.