Android TextView实现超过固定行数折叠内容
2022-11-24 本文已影响0人
愿天深海
在之前的文章Android TextView 动态设置缩进距离中实现了在TextView前端加入一个标签展示,并将TextView动态缩进标签长度距离。
这次的小需求是,当TextView中的内容超过固定行数时,需要折叠内容显示...并在后面拼接show more字样,点击之后将折叠内容全部展示并在后面拼接hide字样。
先来看一下最终效果图:
点击展开之后: 最终效果图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
}
}