web-dev-qa-db-fra.com

comment faire un texte spécifique sur TextView BOLD

Je ne sais pas comment faire en sorte qu'un texte spécifique sur TextView soit en gras.

c'est comme ça

txtResult.setText(id+" "+name);

Je veux que la sortie soit comme ça:

1111 neil

id et name sont des variables dont j'ai récupéré la valeur dans la base de données, et je veux mettre en gras la id, mais uniquement la id afin que la name ne soit pas affectée, je ne sais pas comment procéder.

171
Budi Darmawan

Il suffit de construire votre chaîne en HTML et de la définir:

String sourceString = "<b>" + id + "</b> " + name; 
mytextview.setText(Html.fromHtml(sourceString));
304
Raghav Sood

Bien que vous puissiez utiliser Html.fromHtml () , vous pouvez utiliser une approche plus native qui est SpannableStringBuilder , ceci post peut être utile.

SpannableStringBuilder str = new SpannableStringBuilder("Your awesome text");
str.setSpan(new Android.text.style.StyleSpan(Android.graphics.Typeface.BOLD), INT_START, INT_END, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv=new TextView(context);
tv.setText(str);
306
wtsang02

Je pensais que la réponse choisie ne donnait pas un résultat satisfaisant. J'ai écrit ma propre fonction qui prend 2 chaînes; Le texte intégral et la partie du texte que vous souhaitez mettre en gras.

Il retourne un SpannableStringBuilder avec le "textToBold" de "text" en gras.

Je trouve la possibilité de mettre une sous-chaîne en gras sans l'envelopper dans des balises utiles.

    /**
     * Makes a substring of a string bold.
     * @param text          Full text
     * @param textToBold    Text you want to make bold
     * @return              String with bold substring
     */

    public static SpannableStringBuilder makeSectionOfTextBold(String text, String textToBold){

        SpannableStringBuilder builder=new SpannableStringBuilder();

        if(textToBold.length() > 0 && !textToBold.trim().equals("")){

            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textToBold.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();
            //for counting start/end indexes

            if(startingIndex < 0 || endingIndex <0){
                return builder.append(text);
            }
            else if(startingIndex >= 0 && endingIndex >=0){

                builder.append(text);
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }else{
            return builder.append(text);
        }

        return builder;
  }
33
Eitan

Premièrement: vous n'avez pas à vous soucier de l'utilisation du code de performance lente de la réponse de Raghav Sood

Deuxièmement: vous n'avez pas besoin d'écrire une fonction d'extension fournie par la réponse de w3bshark lorsque vous utilisez Kotlin.

Finnaly: Tout ce que vous avez à faire est d’utiliser la bibliothèque Kotlin Android-ktx de Google:

// Suppose id = 1111 and name = neil (just what you want). 
val s = SpannableStringBuilder()
          .bold { append(id) } 
          .append(name)
txtResult.setText(s) 

Produit: 1111 neil


METTRE À JOUR:

Parce que je pense que cela peut aider quelqu'un d'autre tout en montrant à quel point vous pouvez aller ici sont des cas d'utilisation plus nombreux.

  • Lorsque vous devez afficher un texte avec certaines parties en bleu et en italique:

    val myCustomizedString = SpannableStringBuilder()
        .color(blueColor, { append("A blue text ") })
        .append("showing that ")
        .italic{ append("it is painless") }
    
  • Lorsque vous devez afficher un texte en gras et en italique:

        bold { italic { append("Bold and italic") } }
    

En bref, bold, append, color et italic sont des fonctions d'extension de SpannableStringBuilder. Vous pouvez voir une autre fonction d’extension dans documentation officielle , à partir de laquelle vous pouvez penser à d’autres possibilités.

24

Comme l'a dit wtsang02, l'utilisation de HTML représente un temps système coûteux. Utilisez simplement la solution native. Si vous n'avez pas à modifier la chaîne, utilisez simplement SpannableString, pas SpannableStringBuilder.

String boldText = "id";
String normalText = "name";
SpannableString str = new SpannableString(boldText + normalText);
str.setSpan(new StyleSpan(Typeface.BOLD), 0, boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(str);
16
Jadamec

Si vous souhaitez utiliser la chaîne à partir de XML, vous pouvez procéder comme suit:

strings.xml

<string name="test">
     <![CDATA[
 <b>bold!</b> normal
    ]]>
</string>

Code:

textView.setText(Html.fromHtml(getString(R.string.test)));
9
android developer

Voici une meilleure solution si vous souhaitez mettre plusieurs textes en gras. J'ai amélioré le code d'Eitan. merci Eitan.

public static SpannableStringBuilder makeSectionOfTextBold(String text, String... textToBold) {
    SpannableStringBuilder builder = new SpannableStringBuilder(text);

    for (String textItem :
            textToBold) {
        if (textItem.length() > 0 && !textItem.trim().equals("")) {
            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textItem.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();

            if (startingIndex >= 0 && endingIndex >= 0) {
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }
    }

    return builder;
}
9
Krishna

Il suffit simplement de fermer le texte spécifié comme ceci, par exemple <b>"your text here:"</b>

<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>

résultat: Siège: Mooresville, Caroline du Nord, États-Unis.

8
Rida

Basé sur la réponse de @ mladj0ni, le code ci-dessous a fonctionné. Le problème était que si vous utilisiez String.format, cela supprimait le balisage html, vous deviez donc échapper aux symboles entre crochets dans strings.xml:

strings.xml:

<string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>

code.Java:

String unspanned = String.format(Locale.US, "%s%s", getResources().getString(R.string. welcome_messages), 99);

Spanned spanned;
if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.N) {
    spanned = Html.fromHtml(unspanned, Html.FROM_HTML_MODE_LEGACY);
} else {
    spanned = Html.fromHtml(unspanned);
}

textView.setText(spanned);

C'est plus simple que SpannableStringBuilder. En ce qui concerne les performances, si vous n’affichez qu’une chaîne, l’utilisateur ne remarquera pas la milliseconde supplémentaire pour l’analyser.

Voir la documentation ici .

6
Yusuf X

Je suis venu ici pour proposer une solution plus à jour, car je n'étais pas satisfait des réponses existantes ... j'avais besoin de quelque chose qui fonctionnerait pour les textes traduits et qui ne soit pas aussi performant que d'utiliser Html.fromHtml() ... .Si vous utilisez Kotlin, voici une fonction d’extension qui permet de régler facilement plusieurs parties de votre texte sur bold . Cela fonctionne comme Markdown et pourrait être étendu pour prendre en charge d’autres balises Markdown, si besoin est.

val yourString = "**This** is your **string**.".makePartialTextsBold()
val anotherString = getString(R.string.something).makePartialTextsBold()

/**
 * This function requires that the parts of the string that need
 * to be bolded are wrapped in ** and ** tags
 */
fun String.makePartialTextsBold(): SpannableStringBuilder {
    var copy = this
    return SpannableStringBuilder().apply {
        var setSpan = true
        var next: String
        do {
            setSpan = !setSpan
            next = if (length == 0) copy.substringBefore("**", "") else copy.substringBefore("**")
            val start = length
            append(next)
            if (setSpan) {
                setSpan(StyleSpan(Typeface.BOLD), start, length,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            copy = copy.removePrefix(next).removePrefix("**")
        } while (copy.isNotEmpty())
    }
}
3
w3bshark

Si vous utilisez Kotlin, il est encore plus facile de le faire en utilisant core-ktx, car il fournit un langage spécifique au domaine (DSL) pour le faire:

val string: SpannedString = buildSpannedString {
    bold {
        append("1111")
    }
    append("neil)     
}

Plus d'options fournies par ce logiciel sont:

append("Hello There")
bold {
    append("bold")
    italic {
        append("bold and italic")
        underline {
            append("then some text with underline")
        }
    }
}

Enfin, vous pouvez simplement:

textView.text = string
3
Devansh Maurya

Faites en sorte que le premier caractère de la chaîne soit spannable lors de la recherche de caractère dans la liste/le recycleur, comme

r a vi et ajay

soulignant précédemment comme ça, mais je voulais être comme ci-dessous

ravi a nd ajayOUravi et a jay

pour cela, j'ai cherché la longueur du mot si elle est égale à 1, j'ai séparé la chaîne principale en mots et calculé la position de départ du mot, puis j'ai cherché le mot commençant par char.

 public static SpannableString colorString(int color, String text, String... wordsToColor) {
    SpannableString coloredString = new SpannableString(text);

    for (String Word : wordsToColor) {

        Log.e("tokentoken", "-wrd len-" + Word.length());
        if (Word.length() !=1) {
            int startColorIndex = text.toLowerCase().indexOf(Word.toLowerCase());
            int endColorIndex = startColorIndex + Word.length();
            try {
                coloredString.setSpan(new ForegroundColorSpan(color), startColorIndex, endColorIndex,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            } catch (Exception e) {
                e.getMessage();
            }
        } else {
            int start = 0;

            for (String token : text.split("[\u00A0 \n]")) {
                if (token.length() > 0) {
                    start = text.indexOf(token, start);
                   // Log.e("tokentoken", "-token-" + token + "   --start--" + start);
                    char x = token.toLowerCase().charAt(0);
                    char w = Word.toLowerCase().charAt(0);
                   // Log.e("tokentoken", "-w-" + w + "   --x--" + x);

                    if (x == w) {
                        // int startColorIndex = text.toLowerCase().indexOf(Word.toLowerCase());
                        int endColorIndex = start + Word.length();
                        try {
                            coloredString.setSpan(new ForegroundColorSpan(color), start, endColorIndex,
                                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                        } catch (Exception e) {
                            e.getMessage();
                        }
                    }
                }
            }

        }

    }

    return coloredString;
}
3
Sagar

J'ai créé une méthode statique pour définissant une partie du texte en gras pour TextView et EditText

public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(Typeface.BOLD); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text normal
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex, contentData.length()-1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
               ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
               ((EditText) mView).setText(sb);

        }
    }

Un autre code plus personnalisé 

  /*typeFaceStyle can be passed as 

    Typeface.NORMAL = 0;
    Typeface.BOLD = 1;
    Typeface.ITALIC = 2;
    Typeface.BOLD_ITALIC = 3;*/

    public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex,int typeFaceStyle){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(typeFaceStyle); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text italic
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex,contentData.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
                ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
                ((EditText) mView).setText(sb);
        }
    }
2
Xar E Ahmer

wtsang02 answer est le meilleur moyen de s’y prendre puisque Html.fromHtml ("") est maintenant obsolète. Ici, je vais juste améliorer un petit peu pour quiconque a du mal à rendre le premier mot audacieux de manière dynamique, quelle que soit la taille de la phrase. 

Commençons par créer une méthode pour obtenir le premier mot:

 private String getFirstWord(String input){

    for(int i = 0; i < input.length(); i++){

        if(input.charAt(i) == ' '){

            return input.substring(0, i);
        }
    }

    return input;
}

Maintenant, disons que vous avez une longue chaîne comme ceci:

String sentence = "[email protected] want's to be your friend!"

Et vous voulez que votre phrase ressemble à [email protected] vous voulez être votre ami! ce:

String myFirstWord = getFirstWord(sentence);
int start = 0; // bold will start at index 0
int end = myFirstWord.length(); // and will finish at whatever the length of your first Word

Maintenant, suivez les étapes de wtsang02 , comme ceci:

SpannableStringBuilder fancySentence = new SpannableStringBuilder(sentence);
fancySentence.setSpan(new Android.text.style.StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(fancySentence);

Et c'est tout! Vous devriez maintenant pouvoir mettre en gras un mot de n'importe quelle taille, comme une phrase longue ou courte. J'espère que ça va aider quelqu'un, codage heureux :)

1
Junia Montana

Vous pouvez ajouter les deux chaînes séparément dans le générateur, l'une d'entre elles est spannedString, l'autre est normale. De cette façon, vous n'avez pas à calculer les index.

val instructionPress = resources?.getString(R.string.settings_press)

val okText = resources?.getString(R.string.ok)
val spannableString = SpannableString(okText)

val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(instructionPress)
spannableBuilder.append(spannableString, StyleSpan(Typeface.BOLD), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

instructionText.setText(spannableBuilder,TextView.BufferType.SPANNABLE)
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
    String resultant = null;

    resultant = textNotBoldFirst + " " + "<b>" + textToBold + "</b>" + " " + textNotBoldLast;

    return Html.fromHtml(resultant);

}

Essaye ça. Cela peut aider définitivement 

1
Saad Bilal

si la position du texte en gras est fixe (ex: if est au début de textView), utilisez deux textView différents avec le même arrière-plan. Ensuite, vous pouvez faire apparaître en gras le textStyle de l'autre textView.

Cela nécessitera deux fois plus de mémoire par rapport à un seul textView mais la vitesse augmentera.

0
neens

C’est la fonction d’extension Kotlin que j’utilise pour cela

/**
 * Sets the specified Typeface Style on the first instance of the specified substring(s)
 * @param one or more [Pair] of [String] and [Typeface] style (e.g. BOLD, ITALIC, etc.)
 */
fun TextView.setSubstringTypeface(vararg textsToStyle: Pair<String, Int>) {
    val spannableString = SpannableString(this.text)
    for (textToStyle in textsToStyle) {
        val startIndex = this.text.toString().indexOf(textToStyle.first)
        val endIndex = startIndex + textToStyle.first.length

        if (startIndex >= 0) {
            spannableString.setSpan(
                StyleSpan(textToStyle.second),
                startIndex,
                endIndex,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
    }
    this.setText(spannableString, TextView.BufferType.SPANNABLE)
}

Usage:

text_view.setSubstringTypeface(
    Pair(
        "something bold",
        Typeface.BOLD
    )
)

.

text_view.setSubstringTypeface(
    Pair(
        "something bold",
        Typeface.BOLD
    ),
    Pair(
        "something italic",
        Typeface.ITALIC
    )
)
0
aaronmarino

Vous pouvez utiliser ce code pour définir une partie de votre texte en gras. Pour tout ce qui est entre les balises HTML gras, cela le rendra en gras.

String myText = "make this <b>bold</b> and <b>this</b> too";
textView.setText(makeSpannable(myText, "<b>(.+?)</b>", "<b>", "</b>"));

public SpannableStringBuilder makeSpannable(String text, String regex, String startTag, String endTag) {

            StringBuffer sb = new StringBuffer();
            SpannableStringBuilder spannable = new SpannableStringBuilder();

            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(text);
            while (matcher.find()) {
                sb.setLength(0);
                String group = matcher.group();
                String spanText = group.substring(startTag.length(), group.length() - endTag.length());
                matcher.appendReplacement(sb, spanText);

                spannable.append(sb.toString());
                int start = spannable.length() - spanText.length();

                spannable.setSpan(new Android.text.style.StyleSpan(Android.graphics.Typeface.BOLD), start, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            sb.setLength(0);
            matcher.appendTail(sb);
            spannable.append(sb.toString());
            return spannable;
        }
0
live-love

Voici ma solution complète pour les valeurs de chaîne dynamiques avec vérification de la casse.

/**
 * Makes a portion of String formatted in BOLD.
 *
 * @param completeString       String from which a portion needs to be extracted and formatted.<br> eg. I am BOLD.
 * @param targetStringToFormat Target String value to format. <br>eg. BOLD
 * @param matchCase Match by target character case or not. If true, BOLD != bold
 * @return A string with a portion formatted in BOLD. <br> I am <b>BOLD</b>.
 */
public static SpannableStringBuilder formatAStringPortionInBold(String completeString, String targetStringToFormat, boolean matchCase) {
    //Null complete string return empty
    if (TextUtils.isEmpty(completeString)) {
        return new SpannableStringBuilder("");
    }

    SpannableStringBuilder str = new SpannableStringBuilder(completeString);
    int start_index = 0;

    //if matchCase is true, match exact string
    if (matchCase) {
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.contains(targetStringToFormat)) {
            return str;
        }

        start_index = str.toString().indexOf(targetStringToFormat);
    } else {
        //else find in lower cases
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.toLowerCase().contains(targetStringToFormat.toLowerCase())) {
            return str;
        }

        start_index = str.toString().toLowerCase().indexOf(targetStringToFormat.toLowerCase());
    }

    int end_index = start_index + targetStringToFormat.length();
    str.setSpan(new StyleSpan(BOLD), start_index, end_index, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return str;
}

Par exemple. completeString = "Je suis gras"

CAS I If *targetStringToFormat* = "bold" et *matchCase* = true 

renvoie "je suis gras" (depuis gras! = gras)

CAS II Si *targetStringToFormat* = "bold" et *matchCase* = false

renvoie "je suisGRAS

Appliquer:

myTextView.setText(formatAStringPortionInBold("I am BOLD", "bold", false))

J'espère que cela pourra aider!

0
sud007