Est-il possible d'Afficher des images en ligne à partir de html dans un logiciel Android TextView?
étant donné le code HTML suivant:
<p>This is text and this is an image <img src="http://www.example.com/image.jpg" />.</p>
est-il possible de faire le rendu de l'image? En utilisant cet extrait: mContentText.setText(Html.fromHtml(text));
, j'obtiens 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 réponses
si vous regardez la documentation pour Html.fromHtml(text)
vous verrez qu'elle dit:
toutes les étiquettes
<img>
dans le HTML s'affichera comme une image de remplacement générique que votre programme peut alors passer par et remplacer par des images réelles.
si vous ne voulez pas faire ce remplacement vous-même, vous pouvez utiliser l'autre Html.fromHtml()
méthode 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 le Html.TagHandler
mais vous avez besoin d'implémenter votre propre Html.ImageGetter
comme il n'y a pas d'implémentation par défaut.
cependant, le problème que vous allez avoir est que le Html.ImageGetter
doit fonctionner de manière synchrone et si vous téléchargez des images à partir du web vous voudrez probablement le faire de façon asynchrone. Si vous pouvez ajouter des images que vous voulez afficher comme ressources dans votre application, votre implémentation ImageGetter
devient beaucoup plus simple. Vous pourriez vous en tirer 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 voudriez probablement trouver quelque chose de plus intelligent pour mapper les chaînes de sources aux identificateurs de ressources.
j'ai mis en œuvre dans mon app ,referece tiré 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);
}
}
}
}
comme indiqué ci-dessous @rpgmaker commentaire j'ai ajouté cette réponse
oui, vous pouvez le faire à l'aide de ResolveInfo classe
vérifiez que votre fichier est pris en charge avec des applications déjà installées ou non
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, qui n'a pas besoin de vous pour hardcore vos noms de ressources et va chercher les ressources dégotables d'abord dans vos ressources apps et puis dans les ressources 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;
}
}
}
pouvant ê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 toutes les balises, récupère les images et les affiche.
ici vous pouvez trouver un code que vous pouvez utiliser (mais il a besoin d'une certaine personnalisation): https://gist.github.com/1190397
j'ai utilisé la réponse de Dave Webb mais je l'ai un peu simplifiée. Aussi longtemps que les ID de ressources resteront les mêmes pendant l'exécution dans votre cas d'utilisation, il n'y a pas vraiment besoin d'écrire votre propre classe en implémentant Html.ImageGetter
et en jouant avec les sources-strings.
ce que j'ai fait était d'utiliser l'ID de ressource comme une source-chaîne:
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 tirer l'URL de toutes les images et ensuite dynamiquement créer de nouvelles imageviews et passer dans les urls.
Aussi, si vous voulez faire le remplacement vous-même, le personnage que vous devez rechercher est [  ].
mais si vous utilisez Eclipse, il va paniquer quand vous tapez cette lettre dans une instruction [replace] vous disant qu'elle entre en conflit avec Cp1252 - c'est un bug Eclipse. Pour le réparer, allez à
Window -> Préférences -> Général -> espace de travail -> fichier Texte encodage,
et sélectionner [UTF-8]
dans le cas où quelqu'un pense que les ressources doivent être déclaratives et l'utilisation de Spannable pour plusieurs langues est un gâchis, j'ai fait une certaine 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;
}
}
}
suivi des mises à jour, s'il y a lieu, à https://gist.github.com/logcat/64234419a935f1effc67