這是我擁有的代碼。
val s = SpannableString("hello")
s.setSpan(StyleSpan(Typeface.BOLD), 0, s.length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
textView.text = TextUtils.concat(s, s)
textView 中顯示的文字是:hello hello
為什么兩個“你好”都不是粗體?
編輯:我實際上是在嘗試將一些SpannableStrings 與一些正常String的 s 連接起來,比如TextUtils.concat("A", s, "B", s, "C")(我期望的結果是 A hello B hello C)。替換SPAN_INCLUSIVE_EXCLUSIVE為SPAN_INCLUSIVE_INCLUSIVE解決了“你好你好”的問題,但不是這個問題。
uj5u.com熱心網友回復:

使用 SPAN_INCLUSIVE_INCLUSIVE:

經過一番挖掘,我發現 TextUtils 正在使用 SpannableStringBuilder.append ,它正在使用 SpannableStringBuilder.replace (https://developer.android.com/reference/android/text/SpannableStringBuilder#replace(int, int, java.lang.CharSequence, int, int) ) 在引擎蓋下,并且替換被認為是最后的插入。使用 SPAN_EXCLUSIVE_INCLUSIVE,它不會擴展格式,而使用 SPAN_INCLUSIVE_INCLUSIVE:
如果源包含帶有 Spanned#SPAN_PARAGRAPH 標志的跨度,并且它不滿足段落邊界約束,則不會保留它。
我還檢查了生成的跨度并列印了 StyleSpan 的開始/結束。第一行帶有 SPAN_EXCLUSIVE_INCLUSIVE 最后一行帶有 SPAN_INCLUSIVE_INCLUSIVE:
01-14 12:44:11.218 5017 5017 E test : span start/end: 0/5
01-14 12:44:22.575 5079 5079 E test : span start/end: 0/10
uj5u.com熱心網友回復:
如果您將文本附加到 a Spannable,那么該文本是純文本還是另一個 都無關緊要Spannable。原始文本中的跨度將根據跨度的標志(Spannable.SPAN_xyz_INCLUSIVEvs Spannable.SPAN_xyz_EXCLUSIVE)擴展或不擴展。TextUtils.concat("A", s, "B", s, "C")這就是為什么粗體格式要么使用(using )擴展到整個字串,Spannable.SPAN_xyz_INCLUSIVE要么根本不擴展 (using Spannable.SPAN_xyz_EXCLUSIVE)。
您嘗試附加已格式化的Spannable內容是行不通的,因為跨度只能使用一次。
這就是為什么:
val s = SpannableStringBuilder("hellohello")
val span = StyleSpan(Typeface.BOLD)
s.setSpan(span, 0, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
s.setSpan(span, 5, 10, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
將導致 hello hello,而這:
val s = SpannableStringBuilder("hellohello")
val span1 = StyleSpan(Typeface.BOLD)
val span2 = StyleSpan(Typeface.BOLD)
s.setSpan(span1, 0, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
s.setSpan(span2, 5, 10, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
將導致你好你好
這回答了你的問題:
為什么兩個“你好”都不是粗體?
不幸的是,您的問題對于您實際想要達到的目標并不是很具體。如果只是簡單地擁有一個Spannablewith A hello B hello C,那么你現在知道如何了。如果您的目標是擁有一個通用解決方案,允許附加任意Spannable跨度并保留這些跨度(CharacterStyle和ParagraphStyle),那么您將必須找到一種方法來克隆Spanned具有任意跨度的任意文本(請注意,如果s是SpannableStringBuilder然后s.subSequence(0, s.length)復制跨度但不不要克隆它們)。所以這就是我的做法:
private fun Spannable.clone(): Spannable {
val clone = SpannableStringBuilder(toString())
for (span in getSpans(0, length, Any::class.java)) {
if (span is CharacterStyle || span is ParagraphStyle) {
val st = getSpanStart(span).coerceAtLeast(0)
val en = getSpanEnd(span).coerceAtMost(length)
val fl = getSpanFlags(span)
val clonedSpan = cloneSpan(span)
clone.setSpan(clonedSpan, st, en, fl)
}
}
return clone
}
private fun cloneSpan(span: Any): Any {
return when (span) {
is StyleSpan -> StyleSpan(span.style)
// more clone code to be written...
else -> span
}
}
然后你可以這樣做:
val s = SpannableString("hello")
s.setSpan(StyleSpan(Typeface.BOLD), 0, s.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = TextUtils.concat(s, " not bold ", s.clone())
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/411479.html
標籤:
