Como fazer parte do texto Negrito no android em tempo de execução?

97

Um ListViewno meu aplicativo tem muitos elementos de cadeia como name, experience, date of joining, etc. Eu só quero fazer namenegrito. Todos os elementos da string estarão em um único TextView.

meu 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>

Meu código para definir o TextView do item ListView:

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

Respostas:

229

Digamos que você tenha uma TextViewligação etx. Você então usaria o seguinte 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
fonte
2
Para Xamarin, use assimvar bss = new StyleSpan(Android.Graphics.TypefaceStyle.Bold);
Elisabeth
Para Xamarin,etx.TextFormatted = sb;
Darius
27

Com base na resposta de Imran Rana, aqui está um método genérico reutilizável se você precisar aplicar StyleSpans a vários TextViews, com suporte para vários idiomas (onde os índices são variáveis):

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

Use-o da seguinte Activitymaneira:

@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:

Bem-vindo ao CompanyName

Friederbluemle
fonte
12

As respostas fornecidas aqui estão corretas, mas não podem ser chamadas em um loop porque o StyleSpanobjeto é uma única extensão contígua (não um estilo que pode ser aplicado a várias extensões). Chamar setSpanvárias vezes com o mesmo negrito StyleSpancriaria um intervalo em negrito e apenas o moveria no intervalo pai.

No meu caso (exibindo os resultados da pesquisa), eu precisava fazer todas as instâncias de todas as palavras-chave da pesquisa aparecerem em negrito. Isso é o que eu fiz:

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

Lembre-se de que o código acima não é inteligente o suficiente para ignorar o negrito duplo se uma palavra-chave for uma substring da outra. Por exemplo, se você pesquisar por "Peixe fi" dentro de "Peixes no mar fisty" , o "peixe" ficará em negrito uma vez e depois a parte "fi" . O bom é que, embora ineficiente e um pouco indesejável, não terá uma desvantagem visual, pois o resultado exibido ainda será

Peixes es na fi Mar sty

copolii
fonte
Ei cara, você pode ver este stackoverflow.com/questions/59947482/…
Pemba Tamang
6

Você pode fazer isso usando Kotlin e buildSpannedStringfunção de extensão decore-ktx

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

se você não sabe exatamente o comprimento do texto antes da parte do texto que deseja transformar em negrito, ou mesmo não sabe o comprimento do texto para ser em negrito, você pode usar facilmente as tags HTML como a seguir:

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

Estendendo a resposta de Frieder para apoiar a insensibilidade a casos e 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
fonte
0

Se você estiver usando a anotação @ srings / your_string, acesse o arquivo strings.xml e use a <b></b>tag na parte do texto que você deseja.

Exemplo:

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

Eu recomendo usar o arquivo strings.xml com CDATA

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

Depois, no arquivo java:

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