Cómo agregar una imagen en un texto TextView?


He buscado en Google y me encontré con este sitio donde encontré una pregunta similar a la mía en la que cómo incluir una imagen en un texto TextView, por ejemplo "hola mi nombre es [imagen]", y la respuesta fue esta:

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

Me gustaría saber en este código,

  1. ¿Qué se supone que debo escribir o hacer en el contexto?
  2. ¿Se supone que debo hacer algo a text.setSpan() como importar o referenciar o dejarlo texto?

Si alguien puede desglosar esto para mí eso sería muy apreciado.

Author: hiergiltdiestfu, 2013-03-12

5 answers

Prueba esto ..

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

Véase también esto.. http://developer.android.com/reference/android/widget/TextView.html

Pruebe esto en el archivo 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"/>
 164
Author: Umesh Lakhani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-12 03:46:47

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

Uso:

{[4] {} En[5]}res/layout/mipresentación.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=...
                />

Tenga en cuenta que si coloca TextViewWithImages.java en algún lugar que no sea com/xyz/customandroid/, también debe cambiar el nombre del paquete, com.xyz.customandroid anterior.

En res/values/strings.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 son iconos en la carpeta res/drawable/

 65
Author: 18446744073709551615,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-31 14:33:35

Esta respuesta se basa en esta excelente respuesta por 18446744073709551615. Su solución, aunque útil, no dimensiona el icono de la imagen con el texto circundante. Tampoco establece el color del icono al del texto circundante.

La solución siguiente toma un icono blanco y cuadrado y hace que se ajuste al tamaño y color del texto circundante.

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

}

Modo de empleo:

Simplemente inserte referencias a los iconos deseados en el texto. No importa si el texto se establece programáticamente a través de textView.setText(R.string.string_resource); o si se establece en xml.

Para incrustar un icono de elemento de diseño llamado ejemplo.png, incluya la siguiente cadena en el texto: [img src=example/].

Por ejemplo, un recurso de cadena podría tener este aspecto:

<string name="string_resource">This [img src=example/] is an icon.</string>
 9
Author: A Boschman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:47

Probé muchas soluciones diferentes y esta para mí fue la mejor:

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

Este código utiliza un mínimo de memoria.

 7
Author: Pavel Kataykin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-28 10:19:12

Esto se basa en parte en esta respuesta anterior de @A Boschman. En esa solución, descubrí que el tamaño de entrada de la imagen afectó en gran medida la capacidad de makeImageSpan() para alinear correctamente el centro de la imagen. Además, descubrí que la solución afectaba el espaciado del texto al crear un espaciado de línea innecesario.

Encontré BaseImageSpan (de la biblioteca de Frescos de Facebook) para hacer el trabajo particularmente bien:

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

Luego proporcione su instancia betterImageSpan a spannable.setSpan() como habitual

 0
Author: kip2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-12 13:25:33