是否有可能在一个TextView中有多个样式?

是否有可能为TextView中的不同部分文本设置多个样式?

例如,我正在设置文本如下:

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

是否有可能为每个文本元素有不同的风格? 例如,line1粗体,word1斜体等

开发者指南的常见任务和如何在Android中执行这些任务包括select,突出显示或设置部分文本样式 :

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

但是在文本中使用显式位置数字。 有没有更干净的方法来做到这一点?

如果有人想知道如何做到这一点,这里有一个办法:(再次感谢Mark!)

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

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

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

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

有点偏离主题,但是我发现这里太有用了,不要在这里提到。

如果我们希望从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> 

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

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

我没有想到这个工作。 但它确实。

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

如果你不喜欢使用html,你可以创build一个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); 

这是一个非常晚的反应,但支持的标签列表在这里: http : //developer.android.com/guide/faq/commontasks.html#selectingtext

这也表明Html.fromHtml并不是真的需要

使用SpannableString代替html标记的重量SpannableString 。 它帮助我看到视觉例子,所以这里是一个补充答案。

在这里输入图像描述

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

进一步研究

  • 解释Span标志的含义,如SPAN_EXCLUSIVE_EXCLUSIVE
  • Android Spanned,SpannedString,Spannable,SpannableString和CharSequence
  • 跨度的types

这个例子最初是从这里启发的。

我遇到了同样的问题。 我可以使用fromHtml,但我现在是Android,而不是networking,所以我决定尝试一下。 我不得不本地化,所以我给了它一个使用stringreplace的概念。 我将TextView上的样式设置为主样式,然后对其他样式进行格式化。

我希望这可以帮助其他人去做同样的事情 – 我不知道为什么在框架中这不是一件容易的事情。

我的string如下所示:

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

现在不推荐使用<b>元素。 <strong>呈现为<b><em>呈现为<i>

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

这对我来说工作得很好

如果您希望能够在xml中添加样式文本,您可以创build一个扩展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); } } 

然后,您可以像这样使用它(用包名称replacePACKAGE_NAME ):

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

这是一个使用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() ); 

结果:

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

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

并在你的Html格式的string中使用这些标签:

 <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

实际上,除了Html对象之外,还可以使用Spannabletypes类,例如TextAppearanceSpan或TypefaceSpan和SpannableString来收集。 Html类也使用这些机制。 但是对于Spannabletypes,你有更多的自由。

这可能像利用String的length()方法一样简单:

  1. 将stringXML文件中的文本string拆分为许多子string(从Android的angular度来看是一个单独的string),因为你需要不同的样式,所以它可能类似于: str1,str2,str3 (就像你的情况一样),当它们连接在一起时,就是你使用的整个单个string。

  2. 然后简单地按照“Span”方法,就像你提供的代码一样 – 而不是一个单一的string,把所有的子string合并成一个,每个都有不同的自定义样式。

你仍然使用数字,但不是直接 – 他们现在不再采取硬编码的forms(如在你的代码中),但是它们被replace为组合的length()方法(注意前后两个星号。用长度()代替绝对数量以便改变变化):

 str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, **str.length()**, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 

对于第一个string大小,则对于第二个string大小,则使用str.length()+ 1,str.length()+ str2.length() ,以此类推,而不是例如0,7或8,19等等…

使用辅助Spannable类作为Androidstring资源共享在网页的底部。 你可以通过创buildCharSquences并给他们一个风格来解决这个问题。

但是在他们给我们的例子中,只是为了大胆,斜体,甚至是文字的着色。 我需要在CharSequence中包装几个样式,以便在TextView设置它们。 所以到那个类(我把它命名为CharSequenceStyles )我只是加了这个函数。

 public static CharSequence applyGroup(LinkedList<CharSequence> content){ SpannableStringBuilder text = new SpannableStringBuilder(); for (CharSequence item : content) { text.append(item); } return text; } 

而在我看来,我加了这个。

  message.push(postMessageText); message.push(limitDebtAmount); message.push(pretMessageText); TextView.setText(CharSequenceStyles.applyGroup(message)); 

我希望这可以帮助你!

Spanny使SpannableString更易于使用。

 Spanny spanny = new Spanny("Underline text", new UnderlineSpan()) .append("\nRed text", new ForegroundColorSpan(Color.RED)) .append("\nPlain text"); textView.setText(spanny) 

我也是

如何使用Kotlin和Anko一些美丽的标记 –

 import org.jetbrains.anko.* override fun onCreate(savedInstanceState: Bundle?) { title = "Created with Beautiful Markup" super.onCreate(savedInstanceState) verticalLayout { editText { hint = buildSpanned { append("Italic, ", Italic) append("highlighted", backgroundColor(0xFFFFFF00.toInt())) append(", Bold", Bold) } } } } 

创建与美丽的标记

正如乔恩所说 ,对我来说这是最好的解决scheme,你不需要在运行时设置任何文本,只使用这个自定义的类HtmlTextView

 public class HtmlTextView extends TextView { public HtmlTextView(Context context) { super(context); } public HtmlTextView(Context context, AttributeSet attrs) { super(context, attrs); } public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(21) public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public void setText(CharSequence s,BufferType b){ super.setText(Html.fromHtml(s.toString()),b); } } 

那就是它,现在只把它放在你的XML中

 <com.fitc.views.HtmlTextView android:id="@+id/html_TV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/example_html" /> 

与您的Htmlstring

 <string name="example_html"> <![CDATA[ <b>Author:</b> Mr Donuthead<br/> <b>Contact:</b> me@donut.com<br/> <i>Donuts for life </i> ]]>