93 votes

Comment ajouter une image dans un TextView ?

J'ai fait des recherches sur Google et je suis tombé sur ce site où j'ai trouvé une question similaire à la mienne, à savoir comment inclure une image dans un message d'accueil. TextView texte, par exemple "bonjour je m'appelle [image]" et la réponse était la suivante :

ImageSpan is = new ImageSpan(context, resId);
text.setSpan(is, index, index + strLength, 0);

Je voudrais savoir dans ce code,

  1. Que suis-je censé taper ou faire dans le contexte ?
  2. Suis-je censé faire quelque chose pour le text.setSpan() comme l'importation ou la référence ou laisser le texte ?

Si quelqu'un peut m'expliquer la situation, j'apprécierais beaucoup.

210voto

Umesh Lakhani Points 2272

Essayez-le.

    txtview.setCompoundDrawablesWithIntrinsicBounds(
                    R.drawable.image, 0, 0, 0);

Voir aussi ceci http://developer.Android.com/reference/Android/widget/TextView.html

Essayez ceci dans le fichier xml

    <TextView
        android:id="@+id/txtStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:drawableLeft="@drawable/image"
        android:drawablePadding="5dp"
        android:maxLines="1"
        android:text="@string/name"/>

79voto

com/xyz/customandroid/ TextViewWithImages .java :

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.text.Spannable;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

public class TextViewWithImages extends TextView {

    public TextViewWithImages(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    public TextViewWithImages(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public TextViewWithImages(Context context) {
        super(context);
    }
    @Override
    public void setText(CharSequence text, BufferType type) {
        Spannable s = getTextWithImages(getContext(), text);
        super.setText(s, BufferType.SPANNABLE);
    }

    private static final Spannable.Factory spannableFactory = Spannable.Factory.getInstance();

    private static boolean addImages(Context context, Spannable spannable) {
        Pattern refImg = Pattern.compile("\\Q[img src=\\E([a-zA-Z0-9_]+?)\\Q/]\\E");
        boolean hasChanges = false;

        Matcher matcher = refImg.matcher(spannable);
    while (matcher.find()) {
        boolean set = true;
        for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) {
            if (spannable.getSpanStart(span) >= matcher.start()
             && spannable.getSpanEnd(span) <= matcher.end()
               ) {
                spannable.removeSpan(span);
            } else {
                set = false;
                break;
            }
        }
        String resname = spannable.subSequence(matcher.start(1), matcher.end(1)).toString().trim();
        int id = context.getResources().getIdentifier(resname, "drawable", context.getPackageName());
        if (set) {
            hasChanges = true;
            spannable.setSpan(  new ImageSpan(context, id),
                                matcher.start(),
                                matcher.end(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                             );
        }
    }

        return hasChanges;
    }
    private static Spannable getTextWithImages(Context context, CharSequence text) {
        Spannable spannable = spannableFactory.newSpannable(text);
        addImages(context, spannable);
        return spannable;
    }
}

Utilisez :

sur res/layout/mylayout.xml :

            <com.xyz.customandroid.TextViewWithImages
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFFFFF00"
                android:text="@string/can_try_again"
                android:textSize="12dip"
                style=...
                />

Notez que si vous placez TextViewWithImages.java dans un endroit autre que com/xyz/customandroid/ vous devez également changer le nom du paquet, com.xyz.customandroid ci-dessus.

sur res/values/chaînes.xml :

<string name="can_try_again">Press [img src=ok16/] to accept or [img src=retry16/] to retry</string>

donde ok16.png y retry16.png sont des icônes dans le res/drawable/ dossier

26voto

Pavel Kataykin Points 831

J'ai essayé de nombreuses solutions différentes et celle-ci était pour moi la meilleure :

SpannableStringBuilder ssb = new SpannableStringBuilder(" Hello world!");
ssb.setSpan(new ImageSpan(context, R.drawable.image), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
tv_text.setText(ssb, TextView.BufferType.SPANNABLE);

Ce code utilise un minimum de mémoire.

16voto

Phan Van Linh Points 16963
fun TextView.addImage(atText: String, @DrawableRes imgSrc: Int, imgWidth: Int, imgHeight: Int) {
    val ssb = SpannableStringBuilder(this.text)

    val drawable = ContextCompat.getDrawable(this.context, imgSrc) ?: return
    drawable.mutate()
    drawable.setBounds(0, 0,
            imgWidth,
            imgHeight)
    val start = text.indexOf(atText)
    ssb.setSpan(VerticalImageSpan(drawable), start, start + atText.length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
    this.setText(ssb, TextView.BufferType.SPANNABLE)
}

VerticalImageSpan classe de grande réponse https://stackoverflow.com/a/38788432/5381331

Utilisation de

val textView = findViewById<TextView>(R.id.textview)
textView.setText("Send an [email-icon] to example@email.com.")
textView.addImage("[email-icon]", R.drawable.ic_email,
        resources.getDimensionPixelOffset(R.dimen.dp_30),
        resources.getDimensionPixelOffset(R.dimen.dp_30))

Résultat

Note
Pourquoi VerticalImageSpan classe ?
ImageSpan.ALIGN_CENTER requiert l'API 29.
Aussi, après le test, je vois que ImageSpan.ALIGN_CENTER ne fonctionne que si l'image est plus petite que le texte, si l'image est plus grande que le texte alors seule l'image est au centre, le texte n'est pas au centre, il s'aligne sur le bas de l'image.

12voto

A Boschman Points 729

Cette réponse est basée sur cette excellente réponse por 18446744073709551615 . Leur solution, bien qu'utile, ne permet pas d'adapter la taille de l'icône de l'image au texte qui l'entoure. Elle ne permet pas non plus d'adapter la couleur de l'icône à celle du texte environnant.

La solution ci-dessous prend une icône blanche et carrée et l'adapte à la taille et à la couleur du texte environnant.

public class TextViewWithImages extends TextView {

    private static final String DRAWABLE = "drawable";
    /**
     * Regex pattern that looks for embedded images of the format: [img src=imageName/]
     */
    public static final String PATTERN = "\\Q[img src=\\E([a-zA-Z0-9_]+?)\\Q/]\\E";

    public TextViewWithImages(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TextViewWithImages(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TextViewWithImages(Context context) {
        super(context);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        final Spannable spannable = getTextWithImages(getContext(), text, getLineHeight(), getCurrentTextColor());
        super.setText(spannable, BufferType.SPANNABLE);
    }

    private static Spannable getTextWithImages(Context context, CharSequence text, int lineHeight, int colour) {
        final Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
        addImages(context, spannable, lineHeight, colour);
        return spannable;
    }

    private static boolean addImages(Context context, Spannable spannable, int lineHeight, int colour) {
        final Pattern refImg = Pattern.compile(PATTERN);
        boolean hasChanges = false;

        final Matcher matcher = refImg.matcher(spannable);
        while (matcher.find()) {
            boolean set = true;
            for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) {
                if (spannable.getSpanStart(span) >= matcher.start()
                        && spannable.getSpanEnd(span) <= matcher.end()) {
                    spannable.removeSpan(span);
                } else {
                    set = false;
                    break;
                }
            }
            final String resName = spannable.subSequence(matcher.start(1), matcher.end(1)).toString().trim();
            final int id = context.getResources().getIdentifier(resName, DRAWABLE, context.getPackageName());
            if (set) {
                hasChanges = true;
                spannable.setSpan(makeImageSpan(context, id, lineHeight, colour),
                        matcher.start(),
                        matcher.end(),
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                );
            }
        }
        return hasChanges;
    }

    /**
     * Create an ImageSpan for the given icon drawable. This also sets the image size and colour.
     * Works best with a white, square icon because of the colouring and resizing.
     *
     * @param context       The Android Context.
     * @param drawableResId A drawable resource Id.
     * @param size          The desired size (i.e. width and height) of the image icon in pixels.
     *                      Use the lineHeight of the TextView to make the image inline with the
     *                      surrounding text.
     * @param colour        The colour (careful: NOT a resource Id) to apply to the image.
     * @return An ImageSpan, aligned with the bottom of the text.
     */
    private static ImageSpan makeImageSpan(Context context, int drawableResId, int size, int colour) {
        final Drawable drawable = context.getResources().getDrawable(drawableResId);
        drawable.mutate();
        drawable.setColorFilter(colour, PorterDuff.Mode.MULTIPLY);
        drawable.setBounds(0, 0, size, size);
        return new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
    }

}

Comment l'utiliser :

Il suffit d'intégrer dans le texte les références aux icônes souhaitées. Peu importe que le texte soit défini de manière programmatique par le biais de la fonction textView.setText(R.string.string_resource); ou si elle est définie dans le xml.

Pour intégrer une icône dessinable nommée exemple.png, incluez la chaîne suivante dans le texte : [img src=example/] .

Par exemple, une ressource de type chaîne peut ressembler à ceci :

<string name="string_resource">This [img src=example/] is an icon.</string>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X