Question Est-il possible d'avoir plusieurs styles dans un TextView?


Est-il possible de définir plusieurs styles pour différents morceaux de texte dans un TextView?

Par exemple, je suis en train de définir le texte comme suit:

tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);

Est-il possible d'avoir un style différent pour chaque élément de texte? Par exemple, ligne1 en gras, mot1 en italique, etc.

Le guide du développeur Tâches courantes et comment les faire dans Android inclut Sélection, mise en évidence ou mise en forme de parties de texte:

// Get our EditText object.
EditText vw = (EditText)findViewById(R.id.text);

// Set the EditText's text.
vw.setText("Italic, highlighted, bold.");

// If this were just a TextView, we could do:
// vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE);
// to force it to use Spannable storage so styles can be attached.
// Or we could specify that in the XML.

// Get the EditText's internal text storage
Spannable str = vw.getText();

// Create our span sections, and assign a format to each.
str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Mais cela utilise des numéros de position explicites dans le texte. Y a-t-il une façon plus propre de le faire?


501
2017-10-07 01:33


origine


Réponses:


Dans le cas, quelqu'un se demande comment faire cela, voici un moyen: (Merci encore à Mark!)

mBox = new TextView(context);
mBox.setText(Html.fromHtml("<b>" + title + "</b>" +  "<br />" + 
            "<small>" + description + "</small>" + "<br />" + 
            "<small>" + DateAdded + "</small>"));

Pour une liste non officielle de balises prises en charge par cette méthode, reportez-vous à ce lien ou cette question: Quels tags HTML sont supportés par Android TextView?


675
2017-10-07 18:58



Essayer Html.fromHtml()et marquez votre texte avec des balises HTML en gras et en italique, par exemple:

Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
textView.setText(text);

206
2017-10-07 13:03



Un peu hors sujet, mais j'ai trouvé cela trop utile pour ne pas être mentionné ici.

Et si nous aimerions lire le texte HTML de string.xml ressources et donc le rendre facile à localiser. CDATA rends cela possible

<string name="my_text">
  <![CDATA[
    <b>Autor:</b> Mr Nice Guy<br/>
    <b>Contact:</b> myemail@grail.com<br/>
    <i>Copyright  2011-2012 Intergalactic Spacebar Confederation </i>
  ]]>
</string> 

À partir de notre code Java, nous pouvons maintenant l'utiliser comme ceci:

TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setText(Html.fromHtml(getString(R.string.my_text))); 

Je ne m'attendais pas à ce que cela fonctionne. Mais ça l'a fait.

J'espère que c'est utile pour certains d'entre vous!


176
2017-11-03 11:20



Si vous n'avez pas envie d'utiliser html, vous pouvez simplement créer un fichier styles.xml et l'utiliser comme ceci:

TextView tv = (TextView) findViewById(R.id.textview);
SpannableString text = new SpannableString(myString);

text.setSpan(new TextAppearanceSpan(getContext(), R.style.myStyle), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new TextAppearanceSpan(getContext(), R.style.myNextStyle), 6, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

tv.setText(text, TextView.BufferType.SPANNABLE);

106
2018-03-14 20:40



La liste des balises prises en charge est la suivante:

Si vous utilisez une ressource de chaîne, vous pouvez ajouter un style simple, tel que gras ou italique en utilisant la notation HTML. Les tags actuellement pris en charge sont les suivants: B (audacieux), I (italique), U (souligner), TT (monospace), BIG, SMALL, SUP (exposant), SUB (indice), et STRIKE (barré). Ainsi, par exemple, dans res/values/strings.xml vous pourriez déclarer ceci:

<resource>
    <string id="@+id/styled_welcome_message">We are <b><i>so</i></b> glad to see you.</string>
</resources>

(De http://developer.android.com/guide/faq/commontasks.html#selectingtext - Lien vers l'archive Web, <resource> la faute de frappe est dans l'original!)

Cela montre aussi que Html.fromHtml n'est pas vraiment nécessaire dans les cas simples.


38
2017-09-02 08:57



Il est plus léger d'utiliser un SpannableString au lieu du balisage HTML. Cela m'aide à voir des exemples visuels, alors voici une réponse supplémentaire.

enter image description here

C'est un simple TextView.

// set the text
SpannableString s1 = new SpannableString("bold\n");
SpannableString s2 = new SpannableString("italic\n");
SpannableString s3 = new SpannableString("foreground color\n");
SpannableString s4 = new SpannableString("background color\n");
SpannableString s5 = new SpannableString("underline\n");
SpannableString s6 = new SpannableString("strikethrough\n");
SpannableString s7 = new SpannableString("bigger\n");
SpannableString s8 = new SpannableString("smaller\n");
SpannableString s9 = new SpannableString("font\n");
SpannableString s10 = new SpannableString("URL span\n");
SpannableString s11 = new SpannableString("clickable span\n");
SpannableString s12 = new SpannableString("overlapping spans\n");

// set the style
int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
s1.setSpan(new StyleSpan(Typeface.BOLD), 0, s1.length(), flag);
s2.setSpan(new StyleSpan(Typeface.ITALIC), 0, s2.length(), flag);
s3.setSpan(new ForegroundColorSpan(Color.RED), 0, s3.length(), flag);
s4.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, s4.length(), flag);
s5.setSpan(new UnderlineSpan(), 0, s5.length(), flag);
s6.setSpan(new StrikethroughSpan(), 0, s6.length(), flag);
s7.setSpan(new RelativeSizeSpan(2), 0, s7.length(), flag);
s8.setSpan(new RelativeSizeSpan(0.5f), 0, s8.length(), flag);
s9.setSpan(new TypefaceSpan("monospace"), 0, s9.length(), flag);
s10.setSpan(new URLSpan("https://developer.android.com"), 0, s10.length(), flag);
s11.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Toast.makeText(getApplicationContext(), "Span clicked", Toast.LENGTH_SHORT).show();
    }
}, 0, s11.length(), flag);
s12.setSpan(new ForegroundColorSpan(Color.RED), 0, 11, flag);
s12.setSpan(new BackgroundColorSpan(Color.YELLOW), 4, s12.length(), flag);
s12.setSpan(new UnderlineSpan(), 4, 11, flag);

// build the string
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(s1);
builder.append(s2);
builder.append(s3);
builder.append(s4);
builder.append(s5);
builder.append(s6);
builder.append(s7);
builder.append(s8);
builder.append(s9);
builder.append(s10);
builder.append(s11);
builder.append(s12);

// set the text view with the styled text
textView.setText(builder);
// enables clicking on spans for clickable span and url span
textView.setMovementMethod(LinkMovementMethod.getInstance());

Une étude plus approfondie

Cet exemple a été inspiré à l'origine de ici.


36
2018-01-31 09:24



Je rencontrais le même problème. Je pourrais utiliser fromHtml, mais je suis Android maintenant, pas web, alors j'ai décidé d'essayer cela. Je dois localiser cela, alors je lui ai donné un coup en utilisant le concept de remplacement de chaîne. Je définis le style sur le TextView comme étant le style principal, puis formate simplement les autres peices.

J'espère que cela aidera les autres qui cherchent à faire la même chose - je ne sais pas pourquoi cela n'est pas plus facile dans le cadre.

Mes chaînes ressemblent à ceci:


<string name="my_text">{0} You will need a {1} to complete this assembly</string>
<string name="text_sub0">1:</string>
<string name="text_sub1">screwdriver, hammer, and measuring tape</string>

Voici les styles:


<style name="MainStyle">
    <item name="android:textSize">@dimen/regular_text</item>
    <item name="android:textColor">@color/regular_text</item>
</style>
<style name="style0">
    <item name="android:textSize">@dimen/paragraph_bullet</item>
    <item name="android:textColor">@color/standout_text</item>
    <item name="android:textStyle">bold</item>
</style>
<style name="style1">
    <item name="android:textColor">@color/standout_light_text</item>
    <item name="android:textStyle">italic</item>
</style>

Voici mon code qui appelle ma méthode formatStyles:


SpannableString formattedSpan = formatStyles(getString(R.string.my_text), getString(R.string.text_sub0), R.style.style0, getString(R.string.main_text_sub1), R.style.style1);
textView.setText(formattedSpan, TextView.BufferType.SPANNABLE);

La méthode de formatage:


private SpannableString formatStyles(String value, String sub0, int style0, String sub1, int style1)
{
    String tag0 = "{0}";
    int startLocation0 = value.indexOf(tag0);
    value = value.replace(tag0, sub0);

    String tag1 = "{1}";
    int startLocation1 = value.indexOf(tag1);
    if (sub1 != null && !sub1.equals(""))
    {
        value = value.replace(tag1, sub1);
    }

    SpannableString styledText = new SpannableString(value);
    styledText.setSpan(new TextAppearanceSpan(getActivity(), style0), startLocation0, startLocation0 + sub0.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    if (sub1 != null && !sub1.equals(""))
    {
        styledText.setSpan(new TextAppearanceSpan(getActivity(), style1), startLocation1, startLocation1 + sub1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    return styledText;
}

16
2018-01-07 23:22



Maintenant le <b> L'élément est obsolète. <strong> rend comme <b>, et <em> rend comme <i>.

tv.setText(Html.fromHtml("<strong>bold</strong> and <em>italic</em> "));

cela fonctionne bien pour moi


12
2017-12-09 11:17



Si vous voulez pouvoir ajouter le texte stylé au format XML, vous pouvez créer une vue personnalisée pour étendre TextView et remplacer setText ():

public class HTMLStyledTextView extends TextView
{
    public HTMLStyledTextView(Context context) {
        super(context);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setText(CharSequence text, BufferType type)
    {
       super.setText(Html.fromHtml(text.toString()), type);
    }
}

Ensuite, vous pouvez l'utiliser comme ceci (remplacer PACKAGE_NAME avec le nom de votre paquet):

<PACKAGE_NAME.HTMLStyledTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="<![CDATA[
        <b>Bolded Text:</b> Non-Bolded Text
    ]]>"
/>

6
2017-08-20 00:07