在之前的文章Android TextView 動態設置縮進距離中實現了在TextView前端加入一個標簽展示,并將TextView動態縮進標簽長度距離。
這次的小需求是,當TextView中的內容超過固定行數時,需要折疊內容顯示...并在后面拼接show more字樣,點擊之后將折疊內容全部展示并在后面拼接hide字樣。
先來看一下最終效果圖:
最終效果圖1
點擊展開之后:
最終效果圖2
不像可以使用LeadingMarginSpan來設置段落縮進距離,這次就沒有官方API可以使用的,我們需要自己去計算。
大致步驟思路:
- 獲取最后拼接字樣的長度s1
- 獲取內容可展示的長度s2:固定行數下長度 - 最后拼接字樣的長度s1
- 在s2長度下,內容設置為展示不下顯示...的顯示長度s3
- 如果s3長度小于內容原本長度,說明在固定行數下是展示不下的,需要步驟3中顯示...的內容拼接最后字樣
- 如果步驟4不滿足,說明在固定行數下是可以展示下的,則需要原本內容拼接最后字樣。
- 最后如果拼接的字樣需要使用不同字體顏色,可以使用ForegroundColorSpan
具體代碼實現如下:
class MainActivity2 : AppCompatActivity() {
private val binding: ActivityMain2Binding by lazy {
ActivityMain2Binding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.hide()
setContentView(binding.root)
//記錄折疊情況,默認為折疊
var collapsed = true
val text =
"This is a very long long long long long long long content, and more than 3 lines it will be collapsed, so it must be very long long long, now it is end."
toggleEllipsize(this, binding.tv, 3, text, "show more", R.color.purple_200)
binding.tv.setOnClickListener {
if (collapsed) {
toggleEllipsize(this, binding.tv, 30, text, " hide", R.color.purple_200)
} else {
toggleEllipsize(this, binding.tv, 3, text, " show more", R.color.purple_200)
}
collapsed = !collapsed
}
}
/**
* 設置textView結尾...后面顯示的文字和顏色
* @param context 上下文
* @param textView textview
* @param maxLines 最大的行數
* @param originText 原文本
* @param endText 結尾文字
* @param endColorID 結尾文字顏色id
*/
private fun toggleEllipsize(
context: Context,
textView: TextView,
maxLines: Int,
originText: String,
endText: String,
endColorID: Int
) {
textView.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val paddingLeft = textView.paddingLeft
val paddingRight = textView.paddingRight
val paint = textView.paint
//獲取最后拼接字樣的長度
val moreText = textView.textSize * endText.length
//獲取內容可展示的長度
val availableTextWidth = (textView.width - paddingLeft - paddingRight) *
maxLines - moreText
val ellipsizeStr: CharSequence = TextUtils.ellipsize(
originText, paint,
availableTextWidth, TextUtils.TruncateAt.END
)
val temp = if (ellipsizeStr.length < originText.length) {
//固定行數下展示不下
ellipsizeStr.toString() + endText
} else {
//固定行數下可以展示下
originText + endText
}
val ssb = SpannableStringBuilder(temp)
ssb.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, endColorID)),
temp.length - endText.length,
temp.length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
textView.text = ssb
textView.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
//最后記得要設置maxLines才能觸發TextView的重新layout
textView.maxLines = maxLines
}
}