Возможно ли иметь несколько стилей внутри TextView? - PullRequest
524 голосов
/ 07 октября 2009

Можно ли установить несколько стилей для разных фрагментов текста внутри TextView?

Например, я задаю текст следующим образом:

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

Возможно ли иметь разные стили для каждого элемента текста? Например, жирная строка 1, курсивное слово 1 и т. Д.

Руководство разработчика Общие задачи и как их выполнять в Android включает Выбор, выделение или стилизация частей текста :

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

Но для этого используются явные номера позиций внутри текста. Есть ли более чистый способ сделать это?

Ответы [ 18 ]

684 голосов
/ 07 октября 2009

В случае, если кому-то интересно, как это сделать, вот один из способов: (Еще раз спасибо Марку!)

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

Неофициальный список тегов, поддерживаемых этим методом, см. по этой ссылке или по этому вопросу: Какие теги HTML поддерживаются в Android TextView?

209 голосов
/ 07 октября 2009

Попробуйте Html.fromHtml() и пометьте текст жирными и курсивом HTML-тегами, например:

Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
textView.setText(text);
183 голосов
/ 03 ноября 2011

Немного не по теме, но я нашел это слишком полезным, чтобы не упоминать здесь.

Что если мы хотим прочитать текст Html из ресурса string.xml и, таким образом, облегчить его локализацию CDATA делают это возможным:

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

Из нашего Java-кода мы теперь можем использовать его следующим образом:

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

Я не ожидал, что это сработает. Но это так.

Надеюсь, это будет полезно для некоторых из вас!

115 голосов
/ 15 марта 2012

Если вы не хотите использовать html, вы можете просто создать файл styles.xml и использовать его так:

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);
46 голосов
/ 31 января 2017

Легче использовать SpannableString вместо HTML-разметки. Это помогает мне видеть наглядные примеры, так что вот дополнительный ответ.

enter image description here

Это один 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());

Дальнейшее изучение

Этот пример был первоначально вдохновлен здесь .

39 голосов
/ 02 сентября 2010

Список поддерживаемых тегов:

Если вы используете строковый ресурс, вы можете добавить несколько простых стилей, таких как полужирный или курсив, используя HTML-нотацию. В настоящее время поддерживаются следующие теги: B (полужирный), I (курсив), U (подчеркивание), TT (моноширинный), BIG, SMALL, SUP (верхний индекс), SUB (нижний индекс) и STRIKE (зачеркнутый). Так, например, в res/values/strings.xml вы можете объявить это:

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

http://developer.android.com/guide/faq/commontasks.html#selectingtext - ссылка на веб-архив, <resource> опечатка в оригинале!)

Это также показывает, что Html.fromHtml на самом деле не требуется в простых случаях.

16 голосов
/ 08 января 2013

Я столкнулся с той же проблемой. Я мог бы использовать fromHtml, но теперь я android, а не web, поэтому я решил попробовать это. Я должен локализовать это, хотя, поэтому я дал ему шанс, используя концепцию замены строки. Я установил стиль в TextView как основной стиль, а затем просто отформатировал другие фрагменты.

Надеюсь, это поможет другим, желающим сделать то же самое - я не знаю, почему это не так просто в рамках.

Мои строки выглядят так:


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

Вот стили:


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

Вот мой код, который вызывает мой метод 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);

Метод форматирования:


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;
}
12 голосов
/ 09 декабря 2013

Теперь элемент <b> устарел. <strong> отображается как <b>, а <em> отображается как <i>.

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

у меня это нормально работает

6 голосов
/ 20 августа 2014

Если вы хотите добавить стилизованный текст в xml, вы можете создать собственное представление, расширяющее TextView и переопределить 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);
    }
}

Затем вы можете использовать его следующим образом (замените PACKAGE_NAME на имя вашего пакета):

<PACKAGE_NAME.HTMLStyledTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="<![CDATA[
        <b>Bolded Text:</b> Non-Bolded Text
    ]]>"
/>
6 голосов
/ 03 октября 2015

Как указано, используйте TextView.setText(Html.fromHtml(String))

И используйте эти теги в строке в формате HTML:

<a href="...">
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font size="..." color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>

http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html

...