Android TextView 中是否可以有多种样式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1529068/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:12:59  来源:igfitidea点击:

Is it possible to have multiple styles inside a TextView?

androidstylestextview

提问by Legend

Is it possible to set multiple styles for different pieces of text inside a TextView?

是否可以为 TextView 中的不同文本段设置多种样式?

For instance, I am setting the text as follows:

例如,我将文本设置如下:

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

Is it possible to have a different style for each text element? E.g., line1 bold, word1 italic, etc.

是否可以为每个文本元素设置不同的样式?例如,line1 粗体、word1 斜体等。

The developer guide's Common Tasks and How to Do Them in Androidincludes Selecting, Highlighting, or Styling Portions of Text:

开发人员指南的常见任务以及如何在 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);
// 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);

But that uses explicit position numbers inside the text. Is there a cleaner way to do this?

但这在文本中使用了明确的位置编号。有没有更干净的方法来做到这一点?

回答by Legend

In case, anyone is wondering how to do this, here's one way: (Thanks to Mark again!)

如果有人想知道如何做到这一点,这是一种方法:(再次感谢马克!)

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

For an unofficial list of tags supported by this method, refer to this linkor this question: Which HTML tags are supported by Android TextView?

有关此方法支持的非官方标签列表,请参阅此链接或此问题:Android TextView 支持哪些 HTML 标签?

回答by CommonsWare

Try Html.fromHtml(), and mark up your text with bold and italic HTML tags e.g:

尝试Html.fromHtml(),并使用粗体和斜体 HTML 标签标记您的文本,例如:

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

回答by Ben

Slightly off-topic, but I found this too useful not to be mentioned here.

有点跑题了,但我发现这太有用了,这里就不提了。

What if we would like to read the the Html text from string.xmlresource and thus make it easy to localize. CDATAmake this possible:

如果我们想从string.xml资源中读取 Html 文本并使其易于本地化,该怎么办CDATA使这成为可能:

<string name="my_text">
  <![CDATA[
    <b>Autor:</b> Mr Nice Guy<br/>
    <b>Contact:</b> [email protected]<br/>
    <i>Copyright ? 2011-2012 Intergalactic Spacebar Confederation </i>
  ]]>
</string> 

From our Java code we could now utilize it like this:

从我们的 Java 代码中,我们现在可以像这样使用它:

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

I did not expect this to work. But it did.

我没想到这会奏效。但它做到了。

Hope it's useful to some of you!

希望对你们中的一些人有用!

回答by Kent Andersen

If you don't feel like using html, you could just create a styles.xml and use it like this:

如果你不想使用 html,你可以创建一个 style.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);

回答by Suragch

It is more light weight to use a SpannableStringinstead of html markup. It helps me to see visual examples so here is a supplemental answer.

使用 aSpannableString而不是 html 标记重量更轻。它帮助我看到视觉示例,所以这里是一个补充答案。

enter image description here

在此处输入图片说明

This is a single TextView.

这是单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());

Further Study

进一步研究

This example was originally inspired from here.

这个例子最初是从这里获得灵感的。

回答by Jon

The list of supported tags is:

支持的标签列表是:

If you use a string resource, you can add some simple styling, such as bold or italic using HTML notation. The currently supported tags are: B(bold), I(italic), U(underline), TT(monospace), BIG, SMALL, SUP(superscript), SUB(subscript), and STRIKE(strikethrough). So, for example, in res/values/strings.xmlyou could declare this:

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

如果您使用字符串资源,您可以添加一些简单的样式,例如使用 HTML 表示法的粗体或斜体。目前支持的标签是:B(粗体), I(斜体), U(下划线), TT(等宽), ,BIGSMALLSUP上标), 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>

(From http://developer.android.com/guide/faq/commontasks.html#selectingtext— Web Archive link, <resource>typo is in original!)

(来自http://developer.android.com/guide/faq/commontasks.html#selectingtext— Web Archive 链接,<resource>错字是原始的!)

It also shows that Html.fromHtmlisn't really needed in simple cases.

它还表明Html.fromHtml在简单的情况下并不真正需要。

回答by farcrats

I was running into the same problem. I could use fromHtml, but I am android now, not web, so I decided to try this out. I do have to localize this though so I gave it a shot using string replacement concept. I set the style on the TextView to be the main style, then just format the other peices.

我遇到了同样的问题。我可以使用 fromHtml,但我现在是 android,不是 web,所以我决定尝试一下。不过,我确实必须对此进行本地化,因此我使用字符串替换概念对其进行了尝试。我将 TextView 上的样式设置为主要样式,然后只设置其他文件的格式。

I hope this helps others looking to do the same thing - I don't know why this isn't easier in the framework.

我希望这可以帮助其他想要做同样事情的人 - 我不知道为什么这在框架中并不容易。

My strings look like this:

我的字符串看起来像这样:


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

Here are the 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>

Here is my code that calls my formatStyles method:

这是调用我的 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);

The format method:

格式化方法:


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

回答by Sandeep P

Now the <b>element is deprecated. <strong>renders as <b>, and <em>renders as <i>.

现在该<b>元素已被弃用。<strong>呈现为<b>,并<em>呈现为<i>

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

this works fine for me

这对我来说很好用

回答by Ilya Gazman

Here is an easy way to do so using HTMLBuilder

这是使用HTMLBuilder执行此操作的简单方法

    myTextView.setText(new HtmlBuilder().
                    open(HtmlBuilder.Type.BOLD).
                    append("Some bold text ").
                    close(HtmlBuilder.Type.BOLD).
                    open(HtmlBuilder.Type.ITALIC).
                    append("Some italic text").
                    close(HtmlBuilder.Type.ITALIC).
                    build()
    );

Result:

结果:

Some bold textSome italic text

一些粗体文本一些斜体文本

回答by Andrew Gallasch

As stated, use TextView.setText(Html.fromHtml(String))

如上所述,使用 TextView.setText(Html.fromHtml(String))

And use these tags in your Html formatted 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

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