Establecer color de TextView span en Android

206

¿Es posible establecer el color del espacio de texto en un TextView?

Me gustaría hacer algo similar a la aplicación de Twitter, en la que una parte del texto es azul. Ver imagen a continuación:

texto alternativo
(fuente: twimg.com )

hpique
fuente

Respuestas:

430

Otra respuesta sería muy similar, pero no necesitaría establecer el texto de las TextViewdos veces

TextView TV = (TextView)findViewById(R.id.mytextview01);

Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");        

wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

TV.setText(wordtoSpan);
DanO
fuente
pero, ¿cómo puedo cambiar el color de varias palabras y todo el texto no un lapso?
mostafa hashim
1
@mostafahashim crea varios tramos repitiendo la línea 3 wordtoSpan.setSpan (nuevo ForegroundColorSpan (Color.RED), 50, 80, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Ashraf Alshahawy
La solución Kotlin + Spannable String se vería así stackoverflow.com/questions/4032676/…
Dmitrii Leonov
82

Aquí hay una pequeña función de ayuda. ¡Ideal para cuando tienes varios idiomas!

private void setColor(TextView view, String fulltext, String subtext, int color) {
    view.setText(fulltext, TextView.BufferType.SPANNABLE);
    Spannable str = (Spannable) view.getText();
    int i = fulltext.indexOf(subtext);
    str.setSpan(new ForegroundColorSpan(color), i, i + subtext.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mach
fuente
38

Siempre encuentro útiles los ejemplos visuales cuando trato de entender un nuevo concepto.

Color de fondo

ingrese la descripción de la imagen aquí

SpannableString spannableString = new SpannableString("Hello World!");
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(backgroundSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);

Color de primer plano

ingrese la descripción de la imagen aquí

SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);

Combinación

ingrese la descripción de la imagen aquí

SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(foregroundSpan, 0, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(backgroundSpan, 3, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);

Estudio adicional

Suragch
fuente
30

Si desea más control, puede consultar la TextPaintclase. Aquí está cómo usarlo:

final ClickableSpan clickableSpan = new ClickableSpan() {
    @Override
    public void onClick(final View textView) {
        //Your onClick code here
    }

    @Override
    public void updateDrawState(final TextPaint textPaint) {
        textPaint.setColor(yourContext.getResources().getColor(R.color.orange));
        textPaint.setUnderlineText(true);
    }
};
Tiago
fuente
getColor (int id) está en desuso en Android 6.0 Marshmallow (API 23) stackoverflow.com/questions/31590714/…
Eka putra
Buena respuesta con Click Listener.
Muhaiminur Rahman
20

Establezca TextViewel texto de su spanable y defina un ForegroundColorSpanpara su texto.

TextView textView = (TextView)findViewById(R.id.mytextview01);    
Spannable wordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");          
wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);    
textView.setText(wordtoSpan);
Jorgesys
fuente
¡Gracias! ¿Es posible hacer esto sin asignar primero el texto a TextView?
hpique
No me expliqué bien. Déjame reformular. ¿Son necesarias las primeras 3 líneas? ¿No puedes crear el objeto Spannable desde la cadena directamente?
hpique
No, tienes que almacenar el texto de TextView en un Buffer Spannable para cambiar el color de primer plano.
Jorgesys
Quiero hacer lo mismo con el color y quiero que todo esté en negrita, excepto la parte de color, esa parte quiero que esté en cursiva, ¿cómo puedo hacer eso?
Lukap
1
¿Cómo establecer clic en el lapso?
Rishabh Srivastava
14

Otra forma que podría usarse en algunas situaciones es establecer el color del enlace en las propiedades de la vista que está tomando el Spannable.

Si su Spannable se va a usar en un TextView, por ejemplo, puede establecer el color del enlace en el XML de esta manera:

<TextView
    android:id="@+id/myTextView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColorLink="@color/your_color"
</TextView>

También puede configurarlo en el código con:

TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setLinkTextColor(your_color);
Dave
fuente
6

Hay una fábrica para crear el Spannable y evitar el reparto, así:

Spannable span = Spannable.Factory.getInstance().newSpannable("text");
Thomas Emil Hansen
fuente
1
¿Podría aclarar cómo usar SpannableFactory? ¿Cómo debería ser el "texto"?
Piotr
después de crear Spannable con SpannableFactory, entonces, ¿cómo usarlo?
MBH
6

El conjunto de colores de texto por el que pasa de cuerdas y el color :

private String getColoredSpanned(String text, String color) {
  String input = "<font color=" + color + ">" + text + "</font>";
  return input;
}

Establezca el texto en TextView / Button / EditText, etc. llamando al siguiente código:

Vista de texto:

TextView txtView = (TextView)findViewById(R.id.txtView);

Obtener cadena de color:

String name = getColoredSpanned("Hiren", "#800000");

Establecer texto en TextView:

txtView.setText(Html.fromHtml(name));

Hecho

Hiren Patel
fuente
5
String text = "I don't like Hasina.";
textView.setText(spannableString(text, 8, 14));

private SpannableString spannableString(String text, int start, int end) {
    SpannableString spannableString = new SpannableString(text);
    ColorStateList redColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{0xffa10901});
    TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, redColor, null);

    spannableString.setSpan(highlightSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannableString.setSpan(new BackgroundColorSpan(0xFFFCFF48), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannableString.setSpan(new RelativeSizeSpan(1.5f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    return spannableString;
}

Salida:

ingrese la descripción de la imagen aquí

Ahamadullah Saikat
fuente
no te gusta Hasina 🤣
Abu Nayem
4

Solo para agregar a la respuesta aceptada, ya que todas las respuestas parecen hablar android.graphics.Colorsolo: ¿qué pasa si el color que quiero está definido res/values/colors.xml?

Por ejemplo, considere los colores de Material Design definidos en colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="md_blue_500">#2196F3</color>
</resources>

( android_material_design_colours.xmles tu mejor amigo)

Luego use ContextCompat.getColor(getContext(), R.color.md_blue_500)donde usaría Color.BLUE, de modo que:

wordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

se convierte en:

wordtoSpan.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.md_blue_500)), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Donde encontré eso:

Antonio Vinicius Menezes Medei
fuente
3

Aquí hay una función de extensión de Kotlin que tengo para esto

    fun TextView.setColouredSpan(word: String, color: Int) {
        val spannableString = SpannableString(text)
        val start = text.indexOf(word)
        val end = text.indexOf(word) + word.length
        try {
            spannableString.setSpan(ForegroundColorSpan(color), start, end,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            text = spannableString
        } catch (e: IndexOutOfBoundsException) {
         println("'$word' was not not found in TextView text")
    }
}

Úselo después de haber configurado su texto en TextView así

private val blueberry by lazy { getColor(R.color.blueberry) }

textViewTip.setColouredSpan("Warning", blueberry)
Ivan Wooll
fuente
1
  1. crear vista de texto en su diseño
  2. pegue este código en su actividad principal

    TextView textview=(TextView)findViewById(R.id.textviewid);
    Spannable spannable=new SpannableString("Hello my name is sunil");
    spannable.setSpan(new ForegroundColorSpan(Color.BLUE), 0, 5, 
    Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    textview.setText(spannable);
    //Note:- the 0,5 is the size of colour which u want to give the strring
    //0,5 means it give colour to starting from h and ending with space i.e.(hello), if you want to change size and colour u can easily
Sunil
fuente
1

A continuación funciona perfectamente para mí

    tvPrivacyPolicy = (TextView) findViewById(R.id.tvPrivacyPolicy);
    String originalText = (String)tvPrivacyPolicy.getText();
    int startPosition = 15;
    int endPosition = 31;

    SpannableString spannableStr = new SpannableString(originalText);
    UnderlineSpan underlineSpan = new UnderlineSpan();
    spannableStr.setSpan(underlineSpan, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

    ForegroundColorSpan backgroundColorSpan = new ForegroundColorSpan(Color.BLUE);
    spannableStr.setSpan(backgroundColorSpan, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

    StyleSpan styleSpanItalic  = new StyleSpan(Typeface.BOLD);

    spannableStr.setSpan(styleSpanItalic, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

    tvPrivacyPolicy.setText(spannableStr);

Salida para el código anterior

ingrese la descripción de la imagen aquí

OmiK
fuente
1

Algunas respuestas aquí no están actualizadas. Porque, en la mayoría de los casos, agregará una acción de clic personalizada en su enlace .

Además, como lo proporciona la ayuda de la documentación, el color del enlace de cadena abarcado tendrá uno predeterminado. "El color de enlace predeterminado es el color de acento del tema o android: textColorLink si este atributo está definido en el tema".

Aquí está la manera de hacerlo de manera segura.

 private class CustomClickableSpan extends ClickableSpan {

    private int color = -1;

    public CustomClickableSpan(){
        super();
        if(getContext() != null) {
            color = ContextCompat.getColor(getContext(), R.color.colorPrimaryDark);
        }
    }

    @Override
    public void updateDrawState(@NonNull TextPaint ds) {
        ds.setColor(color != -1 ? color : ds.linkColor);
        ds.setUnderlineText(true);
    }

    @Override
    public void onClick(@NonNull View widget) {
    }
}

Entonces para usarlo.

   String text = "my text with action";
    hideText= new SpannableString(text);
    hideText.setSpan(new CustomClickableSpan(){

        @Override
        public void onClick(@NonNull View widget) {
            // your action here !
        }

    }, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    yourtextview.setText(hideText);
    // don't forget this ! or this will not work !
    yourtextview.setMovementMethod(LinkMovementMethod.getInstance());

Espero que esto sea de gran ayuda!

Zhar
fuente
1

Desde los documentos del desarrollador, para cambiar el color y el tamaño de un spannable:

1- crea una clase:

    class RelativeSizeColorSpan(size: Float,@ColorInt private val color: Int): RelativeSizeSpan(size) {

    override fun updateDrawState(textPaint: TextPaint?) {
        super.updateDrawState(textPaint)
        textPaint?.color = color
    } 
}

2 Crea tu spannable usando esa clase:

    val spannable = SpannableStringBuilder(titleNames)
spannable.setSpan(
    RelativeSizeColorSpan(1.5f, Color.CYAN), // Increase size by 50%
    titleNames.length - microbe.name.length, // start
    titleNames.length, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
Badr
fuente