web-dev-qa-db-fra.com

Est-il possible d'afficher des images en ligne à partir de HTML dans un 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 rendre l'image? Lors de l'utilisation de cet extrait: mContentText.setText(Html.fromHtml(text));, je reçois une boîte cyan avec des bordures noires, ce qui me laisse penser qu'un TextView a une idée de ce qu'est une balise img.

82
Gunnar Lium

Si vous regardez la documentation pour Html.fromHtml(text) vous verrez qu'il est écrit:

Toutes les balises <img> Dans le code HTML s’afficheront sous la forme d’une image de remplacement générique que votre programme pourra ensuite parcourir et remplacer par des images réelles.

Si vous ne voulez pas faire ce remplacement 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 le Html.TagHandler, Mais vous devrez implémenter votre propre Html.ImageGetter Car 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 manière asynchrone. Si vous pouvez ajouter des images que vous souhaitez afficher en tant que ressources dans votre application, votre implémentation de 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 voudrez probablement trouver quelque chose de plus intelligent pour mapper les chaînes source aux ID de ressources.

124
Dave Webb

J'ai implémenté dans mon application, pris referece du pskink . Merci 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 ci-dessous @rpgmaker commenter j'ai ajouté cette réponse

oui vous pouvez faire en utilisant ResolveInfo class

vérifiez si 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;
    }
}
16
madhu sudhan

C’est ce que j’utilise, ce qui n’a pas besoin de vous forcer à nommer vos noms de ressources et cherchera d’abord les ressources que l’on peut dessiner dans les ressources de vos applications, puis dans le stock Android ressources si rien n’a été trouvé - permettant vous 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;
        }
     }

 }

Qui peut être utilisé tel quel (exemple):

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

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

Ici vous pouvez trouver du code que vous pouvez utiliser (mais cela nécessite une personnalisation): https://Gist.github.com/1190397

5
Julian

J'ai utilisé la réponse de Dave Webb, mais je l'ai un peu simplifiée. Tant que les ID de ressource resteront les mêmes pendant l'exécution dans votre cas d'utilisation, il n'est pas vraiment nécessaire d'écrire votre propre classe en implémentant Html.ImageGetter et déconner avec les chaînes de source.

J'ai utilisé l'ID de ressource comme chaîne source:

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

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

1
Falmarri

De plus, si vous souhaitez effectuer le remplacement vous-même, le caractère que vous devez rechercher est [].

Mais si vous utilisez Eclipse, il s’effraiera de paniquer si vous tapez cette lettre dans une instruction [replace] vous indiquant qu’il entre en conflit avec Cp1252 - il s’agit d’un bogue 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]

1
splash

Dans le cas où quelqu'un pense que les ressources doivent être déclaratives et que Spannable est utilisé dans plusieurs langues, c'est un gâchis, j'ai créé 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, sur https://Gist.github.com/logcat/64234419a935f1effc67

0
logcat