是否可以在TextView中为不同的文本设置多种样式?
例如,我将文本设置如下:
tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);
每个文本元素是否可以具有不同的样式? 例如,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);
但这在文本中使用了明确的位置编号。 有没有更清洁的方法可以做到这一点?
#1楼
我遇到了同样的问题。 我可以使用fromHtml,但是我现在是android,而不是网络,所以我决定尝试一下。 我确实必须对此进行本地化,因此我使用字符串替换概念给了它一个镜头。 我将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;
}
#2楼
尝试使用Html.fromHtml()
,并用粗体和斜体HTML标签标记文本,例如:
Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
textView.setText(text);
#3楼
万一有人想知道如何做到这一点,这是一种方法:(再次感谢Mark!)
mBox = new TextView(context);
mBox.setText(Html.fromHtml("<b>" + title + "</b>" + "<br />" +
"<small>" + description + "</small>" + "<br />" +
"<small>" + DateAdded + "</small>"));
有关此方法支持的标签的非正式列表,请参考此链接或以下问题: Android TextView支持哪些HTML标签?
#4楼
现在不推荐使用<b>
元素。 <strong>
呈现为<b>
,而<em>
呈现为<i>
。
tv.setText(Html.fromHtml("<strong>bold</strong> and <em>italic</em> "));
#5楼
实际上,除了Html对象外,您还可以使用Spannable类型类,例如TextAppearanceSpan或TypefaceSpan和SpannableString。 HTML类也使用这些机制。 但是,有了Spannable类型类,您将拥有更多的自由。
#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);
}
}
然后,您可以像这样使用它(将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
]]>"
/>
#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()
);
结果:
一些粗体文本 一些斜体文本
#8楼
如前所述,使用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
#9楼
支持的标签列表为:
如果使用字符串资源,则可以添加一些简单的样式,例如使用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 — Web存档链接, <resource>
错字是原始的!)
它还表明,在简单情况下实际上并不需要Html.fromHtml
。
#10楼
它可能与利用String的length()方法一样简单:
根据需要的样式,将Strings XML文件中的文本字符串拆分为尽可能多的子字符串(从Android的角度来看是单独的字符串),就像: str1,str2,str3 (视情况而定),当连接在一起时,就是您使用的整个单个字符串。
然后,只需遵循“ Span”方法,就像您在代码中所看到的一样,但是将单个子字符串合并为一个子字符串,而不是单个字符串,而是将所有子字符串合并为一个子字符串,每个子字符串都有不同的自定义样式。
您仍然可以使用数字,但是不能直接使用-现在不再采用硬编码形式(如您的代码中那样),而是将它们替换为合并的length()方法(请注意在str的前面和后缀有两个星号)。用length()代替绝对值来消除更改):
str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, **str.length()**, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
对于第一个字符串大小,然后是str.length()+ 1,str.length()+ str2.length()对于第二个字符串大小,依此类推,包括所有子字符串,而不是例如0.7或8,19等等...
#11楼
使用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());
进一步研究
- 解释Span标志的含义,例如SPAN_EXCLUSIVE_EXCLUSIVE
- Android Spanned,SpannedString,Spannable,SpannableString和CharSequence
- 跨度类型
这个例子最初是从这里得到启发的。
#12楼
在网页底部使用辅助Spannable类作为Android String Resources共享。 您可以通过创建CharSquences
并为其指定样式来解决此问题。
但是在他们给我们的示例中,仅用于粗体,斜体甚至是着色文本。 我需要在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));
希望对您有所帮助!
#13楼
Spanny使SpannableString易于使用。
Spanny spanny = new Spanny("Underline text", new UnderlineSpan())
.append("\nRed text", new ForegroundColorSpan(Color.RED))
.append("\nPlain text");
textView.setText(spanny)
#14楼
正如乔恩所说 ,对我来说这是最好的解决方案,您不需要在运行时设置任何文本,只需使用此自定义类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" />
与您的HTML字符串
<string name="example_html">
<![CDATA[
<b>Author:</b> Mr Donuthead<br/>
<b>Contact:</b> me@donut.com<br/>
<i>Donuts for life </i>
]]>
#15楼
我也是
如何在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)
}
}
}
}
#16楼
是的,可以使用SpannedString
。 如果您使用的是Kotlin,则使用core-ktx
变得更加容易,因为它提供了一种特定于域的语言(DSL) :
val string: SpannedString = buildSpannedString {
bold {
append("1111")
}
append("Devansh")
}
它提供的更多选项是:
append("Hello There")
bold {
append("bold")
italic {
append("bold and italic")
underline {
append("then some text with underline")
}
}
}
最后,您可以执行以下操作:
textView.text = string
#17楼
如果您使用的是Kotlin,则使用core-ktx
变得更加容易,因为它提供了一种特定于域的语言(DSL) :
val string: SpannedString = buildSpannedString {
bold {
append("1111")
}
append("neil)
}
它提供的更多选项是:
append("Hello There")
bold {
append("bold")
italic {
append("bold and italic")
underline {
append("then some text with underline")
}
}
}
最后,您可以执行以下操作:
textView.text = string
#18楼
有点题外话,但我发现它太有用了,这里不予提及。
resource and thus make it easy to localize. 如果我们想从资源中读取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)));
我没想到这行得通。 但是确实如此。
希望对您中的某些人有用!
#19楼
如果您不想使用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);