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);
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);
D'après la réponse d'Imran Rana, voici une méthode générique et réutilisable si vous devez appliquer StyleSpan
s à plusieurs TextView
s, 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
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
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"));
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);
}