web-dev-qa-db-fra.com

Comment intégrer une partie du texte en gras dans Android lors de l'exécution?

Un ListView dans mon application contient de nombreux éléments de chaîne tels que name, experience, date of joining, etc. Je veux juste mettre name en gras. Tous les éléments de chaîne seront dans une seule TextView.

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

Mon code pour définir le TextView de l'élément ListView:

holder.text.setText(name + "\n" + expirience + " " + dateOfJoininf);
66
Housefly

Disons que vous avez une TextView appelée etx. Vous utiliseriez alors le code suivant:

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

184
Imran Rana

D'après la réponse d'Imran Rana, voici une méthode générique et réutilisable si vous devez appliquer StyleSpans à plusieurs TextViews, avec prise en charge de plusieurs langues (où les indices sont 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);
}

Utilisez-le dans une Activity comme ceci:

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

Résultat:

Bienvenue dans CompanyName

17
friederbluemle

Les réponses fournies ici sont correctes, mais ne peuvent pas être appelées dans une boucle car l'objet StyleSpan est une plage unique et contigue (pas un style pouvant être appliqué à plusieurs plages). Si vous appelez setSpan plusieurs fois avec le même caractère gras StyleSpan, vous créez un tiret gras et vous ne faites que le déplacer dans la portée parent.

Dans mon cas (affichage des résultats de recherche), je devais mettre toutes les occurrences de tous les mots clés de recherche en gras. C'est ce que j'ai fait:

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

Gardez à l'esprit que le code ci-dessus n'est pas assez intelligent pour ignorer le double caractère si un mot clé est une sous-chaîne de l'autre. Par exemple, si vous recherchez "Fish fi" dans "Des poissons dans la mer poilue", le "poisson" sera en gras une fois, puis le "fi". portion. La bonne chose est que, même s’il est inefficace et un peu indésirable, il n’aura pas d’inconvénient visuel, car le résultat affiché sera toujours similaire.

Poisson es dans la fi mer bleue

7
copolii

si vous ne connaissez pas exactement la longueur du texte avant la portion de texte que vous souhaitez mettre en gras, ou même si vous ne connaissez pas la longueur du texte en gras, vous pouvez facilement utiliser des balises HTML comme suit:

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

Extension de la réponse de frieder pour soutenir l'insensibilité aux cas et aux signes diacritiques.

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