是否可以在TextView中包含多个样式?

Leg*_*end 532 android styles textview

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

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

tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);
Run Code Online (Sandbox Code Playgroud)

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

开发人员指南的常见任务和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);
Run Code Online (Sandbox Code Playgroud)

但是它在文本中使用了明确的位置编号.有更清洁的方法吗?

Leg*_*end 688

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

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

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

  • 为什么这不起作用`mBox..setText(Html.fromHtml(“ &lt;​​b&gt;” +名称+“ &lt;/ b&gt;”)+ doNotApplyHTML);`任何想法,谢谢 (2认同)

Com*_*are 211

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

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

  • 我不知道Html.fromHtml()支持的完整标签名单 - 你需要查看源代码.内联标记和多个TextView小部件应该是正交决策.如果需要精确放置不连续的文本位,请使用多个小部件.如果您在小部件中需要内联标记,请使用内联标记.请记住:Android中没有FlowLayout,因此将多个TextView串联起来创建一个段落并不是真正实用的AFAIK. (2认同)
  • @TimBoland:你可以做到这一切:`monthYearLabel.setText(Html.fromHtml("<b>"+ month.getMonthLabel().toUpperCase()+"</ b>&nbsp;"+ month.getYearLabel() )),如果你不需要单件. (2认同)

Ben*_*Ben 184

稍微偏离主题,但我觉得这个太有用了,不在这里提及.

如果我们想从string.xml资源中读取Html文本并因此可以轻松进行本地化,该怎么办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> 
Run Code Online (Sandbox Code Playgroud)

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

TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setText(Html.fromHtml(getString(R.string.my_text))); 
Run Code Online (Sandbox Code Playgroud)

我没想到这会起作用.但确实如此.

希望它对你们有些人有用!

  • 我发现这是最好的答案.启发了我.忍不住把我的两分钱的价值回答.解决方案https://gist.github.com/aegis1980/b138dcb2fd1b2e98aa30允许您在布局文件中分配,因此您无需以编程方式分配文本资源(并且可以在Android Studio中预览!) (3认同)
  • 通常"false"表示您在查找表上访问了一个奇怪的值.当我有R.id.ok和R.string.ok时,我得到了这个,并且意外地使用了getString(R.id.ok)而不是正确的getString(R.string.ok) (2认同)

Ken*_*sen 119

如果你不想使用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);
Run Code Online (Sandbox Code Playgroud)

  • 我不明白为什么l10n无法使用此解决方案.只需获取单独的字符串而不只是一个:String firstPart = getString(R.string.line1); String secondPart = getString(R.string.line2); Spannable text = new SpannableString(firstPart + secondPart); text.setSpan(new ForegroundColorSpan(Color.parseColor(TEXT_COLOR_FOR_FIRST_PART)),0,firstPart.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); myTextView.setText(text,TextView.BufferType.SPANNABLE); (9认同)
  • @Rui因为l10n也是位置的.你不能硬编码短语中单词的位置,仍然是l10n.这就是为什么你在字符串包中看到"$ 1%s是一个快乐的$ 2%s"的原因.你必须允许重新安排令牌. (5认同)
  • 考虑到l10n的担忧,我不知道这是如何工作的. (2认同)

Sur*_*gch 48

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

在此输入图像描述

这是一个单一的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());
Run Code Online (Sandbox Code Playgroud)

进一步研究

这个例子最初的灵感来自这里.

  • 您的帖子比关于SpannableString的Google文档好.谢谢 (5认同)

小智 40

支持的标签列表是:

如果使用字符串资源,则可以使用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>
Run Code Online (Sandbox Code Playgroud)

(来自http://developer.android.com/guide/faq/commontasks.html#selectingtext - 网络档案链接,<resource>拼写错误!)

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


far*_*ats 16

我遇到了同样的问题.我可以使用fromHtml,但我现在是android,而不是web,所以我决定尝试一下.我必须将其本地化,所以我使用字符串替换概念给它一个镜头.我将TextView上的样式设置为主要样式,然后格式化其他peices.

我希望这有助于其他人做同样的事情 - 我不知道为什么在框架中这不容易.

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


<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>
Run Code Online (Sandbox Code Playgroud)

以下是款式:


<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>
Run Code Online (Sandbox Code Playgroud)

这是我调用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);
Run Code Online (Sandbox Code Playgroud)

格式方法:


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;
}
Run Code Online (Sandbox Code Playgroud)


San*_*p P 13

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

tv.setText(Html.fromHtml("<strong>bold</strong> and <em>italic</em> "));
Run Code Online (Sandbox Code Playgroud)

这对我来说很好


Dev*_*rya 8

是的,可以使用SpannedString. 如果您使用的是 Kotlin,那么使用 会变得更加容易core-ktx,因为它提供了一种领域特定语言 (DSL)来执行此操作:

    val string: SpannedString = buildSpannedString {
        bold {
            append("1111")
        }
        append("Devansh")     
    }
Run Code Online (Sandbox Code Playgroud)

它提供的更多选项是:

append("Hello There")
bold {
    append("bold")
    italic {
        append("bold and italic")
        underline {
            append("then some text with underline")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,您可以:

textView.text = string
Run Code Online (Sandbox Code Playgroud)


Ily*_*man 7

使用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()
    );
Run Code Online (Sandbox Code Playgroud)

结果:

一些粗体文字 一些斜体文字


bco*_*rso 6

如果您希望能够在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以像这样使用它(替换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
    ]]>"
/>
Run Code Online (Sandbox Code Playgroud)


And*_*sch 6

如上所述,使用 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>
Run Code Online (Sandbox Code Playgroud)

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