¿Cómo hacer parte del texto en negrita en Android en tiempo de ejecución?

97

A ListViewmi solicitud tiene muchos elementos de cuerda como name, experience, date of joining, etc. Yo sólo quiero hacer namenegrita. Todos los elementos de la cadena estarán en un solo TextView.

mi XML:

<ImageView
    android:id="@+id/logo"
    android:layout_width="55dp"
    android:layout_height="55dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="15dp" >
</ImageView>

<TextView
    android:id="@+id/label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/logo"
    android:padding="5dp"
    android:textSize="12dp" >
</TextView>

Mi código para configurar el TextView del elemento ListView:

holder.text.setText(name + "\n" + expirience + " " + dateOfJoininf);
Mosca doméstica
fuente

Respuestas:

230

Digamos que tiene una TextViewllamada etx. Luego usaría el siguiente código:

final SpannableStringBuilder sb = new SpannableStringBuilder("HELLOO");

final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD); // Span to make text bold
final StyleSpan iss = new StyleSpan(android.graphics.Typeface.ITALIC); //Span to make text italic
sb.setSpan(bss, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold 
sb.setSpan(iss, 4, 6, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make last 2 characters Italic

etx.setText(sb);

Imran Rana
fuente
2
Para Xamarin, use asívar bss = new StyleSpan(Android.Graphics.TypefaceStyle.Bold);
Elisabeth
Para Xamarin,etx.TextFormatted = sb;
Darius
27

Según la respuesta de Imran Rana, aquí hay un método genérico y reutilizable si necesita aplicar StyleSpans a varios TextViews, con soporte para múltiples idiomas (donde los índices son variables):

void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style) {
    SpannableStringBuilder sb = new SpannableStringBuilder(text);
    int start = text.indexOf(spanText);
    int end = start + spanText.length();
    sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    textView.setText(sb);
}

Úselo de una Activitymanera similar:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    StyleSpan boldStyle = new StyleSpan(Typeface.BOLD);
    setTextWithSpan((TextView) findViewById(R.id.welcome_text),
        getString(R.string.welcome_text),
        getString(R.string.welcome_text_bold),
        boldStyle);

    // ...
}

strings.xml

<string name="welcome_text">Welcome to CompanyName</string>
<string name="welcome_text_bold">CompanyName</string>

Resultado:

Bienvenido a CompanyName

friederbluemle
fuente
12

Las respuestas proporcionadas aquí son correctas, pero no se pueden llamar en un bucle porque el StyleSpanobjeto es un solo tramo contiguo (no es un estilo que se pueda aplicar a varios tramos). Llamar setSpanvarias veces con la misma negrita StyleSpancrearía un intervalo en negrita y simplemente lo movería en el intervalo principal.

En mi caso (mostrar resultados de búsqueda), necesitaba que todas las instancias de todas las palabras clave de búsqueda aparecieran en negrita. Esto es lo que hice:

private static SpannableStringBuilder emboldenKeywords(final String text,
                                                       final String[] searchKeywords) {
    // searching in the lower case text to make sure we catch all cases
    final String loweredMasterText = text.toLowerCase(Locale.ENGLISH);
    final SpannableStringBuilder span = new SpannableStringBuilder(text);

    // for each keyword
    for (final String keyword : searchKeywords) {
        // lower the keyword to catch both lower and upper case chars
        final String loweredKeyword = keyword.toLowerCase(Locale.ENGLISH);

        // start at the beginning of the master text
        int offset = 0;
        int start;
        final int len = keyword.length(); // let's calculate this outside the 'while'

        while ((start = loweredMasterText.indexOf(loweredKeyword, offset)) >= 0) {
            // make it bold
            span.setSpan(new StyleSpan(Typeface.BOLD), start, start+len, SPAN_INCLUSIVE_INCLUSIVE);
            // move your offset pointer 
            offset = start + len;
        }
    }

    // put it in your TextView and smoke it!
    return span;
}

Tenga en cuenta que el código anterior no es lo suficientemente inteligente como para omitir el doble negrita si una palabra clave es una subcadena de la otra. Por ejemplo, si busca "Fish fi" dentro de "Fishes in the fisty Sea" , el "pez" aparecerá en negrita una vez y luego la parte "fi" . Lo bueno es que, si bien es ineficiente y un poco indeseable, no tendrá un inconveniente visual, ya que el resultado que se muestra todavía se verá como

Pescado es en la fi Mar pocilga

copolii
fuente
Hola, ¿puedes ver esto? stackoverflow.com/questions/59947482/…
Pemba Tamang
6

Puedes hacerlo usando Kotlin y la buildSpannedStringfunción de extensión desdecore-ktx

 holder.textView.text = buildSpannedString {
        bold { append("$name\n") }
        append("$experience $dateOfJoining")
 }
Dmitrii Leonov
fuente
5

Si no sabe exactamente la longitud del texto antes de la parte de texto que desea poner en negrita, o incluso si no sabe la longitud del texto en negrita, puede usar fácilmente etiquetas HTML como las siguientes:

yourTextView.setText(Html.fromHtml("text before " + "<font><b>" + "text to be Bold" + "</b></font>" + " text after"));
Muhammed Refaat
fuente
0

Extendiendo la respuesta de frieder para apoyar la insensibilidad a los casos y los diacríticos.

public static String stripDiacritics(String s) {
        s = Normalizer.normalize(s, Normalizer.Form.NFD);
        s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");
        return s;
}

public static void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style, boolean caseDiacriticsInsensitive) {
        SpannableStringBuilder sb = new SpannableStringBuilder(text);
        int start;
        if (caseDiacriticsInsensitive) {
            start = stripDiacritics(text).toLowerCase(Locale.US).indexOf(stripDiacritics(spanText).toLowerCase(Locale.US));
        } else {
            start = text.indexOf(spanText);
        }
        int end = start + spanText.length();
        if (start > -1)
            sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(sb);
    }
luky
fuente
0

Si está usando la anotación @ srings / your_string, acceda al archivo strings.xml y use la <b></b>etiqueta en la parte del texto que desee.

Ejemplo:

    <string><b>Bold Text</b><i>italic</i>Normal Text</string>
Isaias Carvalho
fuente
-1

Recomiendo usar el archivo strings.xml con CDATA

<string name="mystring"><![CDATA[ <b>Hello</b> <i>World</i> ]]></string>

Luego, en el archivo java:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);
myTextView.setText(Html.fromHtml( getResources().getString(R.string.mystring) ));
sonique
fuente