web-dev-qa-db-fra.com

Comment ajouter une image dans un texte TextView?

J'ai effectué des recherches sur Google et suis tombé sur ce site où j'ai trouvé une question similaire à la mienne, qui explique comment inclure une image dans un texte TextView, par exemple "hello my name is [image]" , et La réponse était la suivante:

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

J'aimerais savoir dans ce code,

  1. Qu'est-ce que je suis censé taper ou faire dans le contexte?
  2. Suis-je censé faire quelque chose à la text.setSpan() comme importer ou référencer ou laisser du texte?

Si quelqu'un peut décomposer cela pour moi, ce serait très apprécié.

69
Cranosaur

Essaye ça ..

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

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

Essayez ceci en 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:singleLine="true"
        Android:text="@string/name"/>
175
Umesh Lakhani

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

Utilisation:

dans 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 emplacement autre que com/xyz/customandroid/, vous devez également modifier le nom du package, com.xyz.customandroid ci-dessus.

dans res/values ​​/ strings.xml:

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

ok16.png et retry16.png sont des icônes du dossier res/drawable/

67

Cette réponse est basée sur cette excellente réponse par 18446744073709551615 . Leur solution, bien que utile, ne redimensionne pas l’icône d’image avec le texte qui l’entoure. De plus, la couleur de l'icône ne correspond pas à 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 utiliser:

Intégrez simplement les références aux icônes souhaitées dans le texte. Peu importe que le texte soit défini par programme via textView.setText(R.string.string_resource); ou qu'il soit défini en xml.

Pour incorporer une icône pouvant être dessinée nommée example.png, incluez la chaîne suivante dans le texte: [img src=example/].

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

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

J'ai essayé beaucoup de solutions différentes et c'é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.

9
Pavel Kataykin

Ceci est en partie basé sur ce réponse précédente de @A Boschman . Dans cette solution, j'ai constaté que la taille d'entrée de l'image affectait grandement la capacité de makeImageSpan() d'aligner correctement le centre de l'image. De plus, j'ai constaté que la solution affectait l'espacement des textes en créant un interligne inutile. 

J'ai trouvé que (BaseImageSpan } _ (de la bibliothèque Fresco de Facebook) était particulièrement efficace:

 /**
 * Create an ImageSpan for the given icon drawable. This also sets the image size. Works best
 * with a square icon because of the sizing
 *
 * @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.
 * @return An ImageSpan, aligned with the bottom of the text.
 */
private static BetterImageSpan makeImageSpan(Context context, int drawableResId, int size) {
    final Drawable drawable = context.getResources().getDrawable(drawableResId);
    drawable.mutate();
    drawable.setBounds(0, 0, size, size);
    return new BetterImageSpan(drawable, BetterImageSpan.ALIGN_CENTER);
}

Ensuite, fournissez votre instance betterImageSpan à spannable.setSpan() comme d'habitude

0
kip2