是否有可能为一个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);
但这使用了文本中的显式位置编号。有更干净的方法吗?
正如Jon所说,对我来说,这是最好的解决方案,你不需要在运行时设置任何文本,只使用这个自定义类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>
]]>
使用SpannableString是实现这一目标的好方法
我使用了几个函数使其易于应用,我将首先解释每个函数的思想,然后显示代码:
String.getAllIndexOf(pattern: String): This will search the patter on the string and return an index list of where the pattern start. Ex: given the string "abcdefabc" and I call the method passing the "abc" as the searched pattern, the method should return the list: listOf(0, 6)
The is a class to receive the pattern and a list of styles (in case you desire to apply different styles to the same pattern in sequence)
SpannableString.applyStyle(context: Context, vararg patternAndStyles: PatternAndStyles): This will apply the styles to the given patterns
现在,在代码上:
getAllIndexOf
fun String.getAllIndexOf(pattern: String): List<Int> {
val allRecordsOfText = mutableListOf<Int>()
var index = 0
while(index >= 0) {
val newStart = if (allRecordsOfText.isEmpty()) {
0
} else {
allRecordsOfText.last() + pattern.length
}
index = this.subSequence(newStart, this.length).indexOf(pattern)
if (index >= 0) {
allRecordsOfText.add(newStart + index)
}
}
return allRecordsOfText.toList()
}
Class to receive the pattern and styles
@Parcelize
class PatternAndStyles(
val pattern: String,
val styles: List<Int>
) : Parcelable
applyStyle
fun SpannableString.applyStyle(context: Context, vararg patternAndStyles: PatternAndStyles) {
for (patternStyle in patternAndStyles.toList()) {
this.toString().getAllIndexOf(patternStyle.pattern).forEachIndexed { index, start ->
val end = start + patternStyle.pattern.length
val styleIndex = if (patternStyle.styles.size > index) index else patternStyle.styles.size - 1
this.setSpan(
TextAppearanceSpan(context, patternStyle.styles[styleIndex]),
start,
end,
SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
How to use it in the end
val stringToApplyStyle = "abc def abc def"
val text = SpannableString(stringToApplyStyle)
text.applyStyle(
this.applicationContext,
PatternAndStyles("abc", listOf(R.style.Style1, R.style.Style2)),
PatternAndStyles("def", listOf(R.style.Style3))
)
The output:
当它被传递给样式到模式“abc”时,两者都被使用
但是在模式“def”中,第二条记录重用了列表中给出的最后一个样式