文本效果
TextView 效果
文本折叠
- 多行折叠和展开
- 设置折叠和展开的文本
- 普通文本和富文本的多行折叠展开支持
- 支持 html 标签
/**
*
* 注意:支持富文本
*
* 超过指定行数后的字符串显示"...See More"或者"...See Less"
* 用法:1.XML:<MoreLessRichTextView></>
* 2.调用MoreLessRichTextView实例对象的showText(text)
* 说明:如果仅仅在xml中或对象创建了一个MoreLessRichTextView,相当于AppCompatTextView使用,必须调用showText(text)函数see more 和 see less才生效
*/
@Suppress("DEPRECATION")
@SuppressLint("WrongConstant")
class MoreLessRichTextView @JvmOverloads constructor(
val mContext: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.textViewStyle
) : AppCompatTextView(mContext, attrs, defStyleAttr) {
// 显示的行数,超过即隐藏,see more替代
private var maxShowLine = -1
private var actualLine = -1
private var tripleDot: String = "..."
private var seeMoreText: String = "See More"
private var seeLessText: String = "See Less"
private var seeMoreTextSize by Delegates.notNull<Float>()
private var seeLessTextSize by Delegates.notNull<Float>()
private var seeMoreTextColor: Int? = null
private var seeLessTextColor: Int? = null
private var shouldAutoExpand: Boolean = true
private var originContentText: CharSequence? = null
private var showState: ShowState = ShowState.EXPAND
private var seeMoreEnable = true
private var seeLessEnable = true
private var moreSpanClickEnable = true
private var lessSpanClickEnable = true
private var setTripleDotShowEnable: ((maxShowLine: Int) -> Boolean) = { true }
private var needFold = false
private var onSpanClickListener: ((state: ShowState) -> Unit)? = null
private var onTextClickListener: OnClickListener? = null
private val showingText = SpannableStringBuilder()
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
breakStrategy = Layout.BREAK_STRATEGY_SIMPLE
}
highlightColor = Color.TRANSPARENT
}
override fun onFinishInflate() {
super.onFinishInflate()
seeMoreTextColor = currentTextColor
seeLessTextColor = currentTextColor
seeMoreTextSize = textSize
seeLessTextSize = textSize
}
private var firstDraw = true
private fun getOriginContentText(): CharSequence {
return originContentText ?: ""
}
private fun getTripleDotTxt(): String {
return if (setTripleDotShowEnable.invoke(maxShowLine)) {
tripleDot
} else {
""
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (!seeMoreEnable && !seeLessEnable) {
return
}
try {
if (firstDraw && maxShowLine >= 0) {
val realLines = if (actualLine >= 0) {
actualLine
} else {
lineCount
}
if (maxShowLine >= realLines) {
needFold = false
return
}
needFold = true
var start = 0
var end: Int
showingText.clear()
for (i in 0 until maxShowLine) {
end = layout.getLineEnd(i)
if (end < 0) {
end = start
}
if (end > getOriginContentText().length) {
end = getOriginContentText().length
}
if (i == maxShowLine - 1) {
val subSequence = getOriginContentText().subSequence(start, end)
val optSeeMoreLineSequence = optSeeMoreLine(subSequence)
showingText.append(optSeeMoreLineSequence)
// if (optSeeMoreLineSequence is Spanned) {
// // Copy existing spans to the new SpannableString
// val spans =
// optSeeMoreLineSequence.getSpans(
// 0,
// subSequence.length,
// Any::class.java
// )
// for (span in spans) {
// val start1 = optSeeMoreLineSequence.getSpanStart(span)
// val end1 = optSeeMoreLineSequence.getSpanEnd(span)
// val flags = optSeeMoreLineSequence.getSpanFlags(span)
// showingText.setSpan(span, start + start1, start + end1, flags)
// }
// }
} else {
val subSequence = getOriginContentText().subSequence(start, end)
showingText.append(subSequence)
}
start = end
}
// 处理下富文本跨行显示异常,将原文本的富文本同步到showingText
val originalText = getOriginContentText()
if (originalText.isNotEmpty() && originalText is Spanned) {
// Copy existing spans to the new SpannableString
val spans = originalText.getSpans(0, originalText.length, Any::class.java)
for (span in spans) {
val s = originalText.getSpanStart(span)
var e = originalText.getSpanEnd(span)
val flags = originalText.getSpanFlags(span)
if (s >= showingText.length) {
continue
}
if (e > showingText.length) {
e = showingText.length
}
showingText.setSpan(span, s, e, flags)
}
}
if (showingText.endsWith("\n")) {
try {
showingText.delete(showingText.length - 1, showingText.length)
} catch (e: Exception) {
//不需要处理,继续使用原字符串即可
}
}
showingText.append("${getTripleDotTxt()} $seeMoreText")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (!seeMoreEnable && !seeLessEnable) {
return
}
try {
if (firstDraw) {
firstDraw = false
if (needFold && showingText.isNotEmpty()) {
setSeeMoreSpan(showingText)
} else {
text = getOriginContentText()
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
//处理最后一行文字的
private fun optSeeMoreLine(rawContent: CharSequence): CharSequence {
//总宽度
val rawWidth = this.measuredWidth
//点点点的宽度
val dotWidth = this.paint.measureText("${getTripleDotTxt()} ")
val rawTextSize = this.paint.textSize
this.paint.textSize = seeMoreTextSize
//see more的宽度
val seeMoreWidth = this.paint.measureText(seeMoreText)
this.paint.textSize = rawTextSize
val rawContextWidth = getTextWidthOrWithReplaceSpanSize(rawContent)
val leftWidth =
rawWidth - rawContextWidth - dotWidth - seeMoreWidth
// Log.d(
// "hacket",
// "rawWidth=$rawWidth, rawContextWidth: $rawContextWidth, leftWidth: $leftWidth, rawContent=$rawContent"
// )
if (leftWidth >= 0) {
return rawContent
}
var tempContent: CharSequence
val expectWidth = rawWidth - dotWidth - seeMoreWidth
for (i in rawContent.indices) {
tempContent = rawContent.subSequence(0, rawContent.length - i)
val tempContentSize = getTextWidthOrWithReplaceSpanSize(tempContent)
if (tempContentSize <= expectWidth) {
// Log.i(
// "hacket",
// "paintWidth: $paintWidth, tempContentSize=$tempContentSize, expectWidth: $expectWidth, tempContent=$tempContent"
// )
return tempContent
}
}
return rawContent
}
/**
* 获取文本宽度,如果文本中包含ReplacementSpan,则需要遍历计算
*
* @param text 文本 CharSequence
*/
private fun getTextWidthOrWithReplaceSpanSize(text: CharSequence?): Float {
if (text == null) {
return 0f
}
val textPaint = paint
var totalWidth = 0f
if (text !is Spanned) { // 普通文本
return textPaint.measureText(text.toString())
}
// 获取所有ReplacementSpan
val spans = text.getSpans(0, text.length, ReplacementSpan::class.java)
var lastSpanEnd = 0
// 遍历所有ReplacementSpan以及普通文本
spans.forEach { span ->
val start = text.getSpanStart(span)
val end = text.getSpanEnd(span)
// 将span前的普通文本宽度添加至totalWidth
if (start > lastSpanEnd) {
val normalTextWidth = textPaint.measureText(text, lastSpanEnd, start)
totalWidth += normalTextWidth
}
// 将ReplacementSpan的宽度添加至totalWidth
val spanWidth = span.getSize(textPaint, text, start, end, null)
totalWidth += spanWidth
lastSpanEnd = end
}
// 将最后一个ReplacementSpan后的普通文本宽度添加至totalWidth
if (lastSpanEnd < text.length) {
val remainingTextWidth = textPaint.measureText(text, lastSpanEnd, text.length)
totalWidth += remainingTextWidth
}
return totalWidth
}
@SuppressLint("ResourceType")
private fun setSeeMoreSpan(newText: CharSequence) {
val spannableString = SpannableString(newText)
// 处理spanned的url点击事件
if (newText is Spanned) {
// Copy existing spans to the new SpannableString
val spans = newText.getSpans(0, newText.length, Any::class.java)
for (span in spans) {
val start = newText.getSpanStart(span)
val end = newText.getSpanEnd(span)
val flags = newText.getSpanFlags(span)
spannableString.setSpan(span, start, end, flags)
}
}
val start = newText.length - seeMoreText.length
val end = newText.length
val flag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
//设置颜色
val colorSpan = ForegroundColorSpan(seeMoreTextColor!!)
spannableString.setSpan(colorSpan, start, end, flag)
//设置字体大小
val sizeSpan = AbsoluteSizeSpan(floor(seeMoreTextSize).toInt())
spannableString.setSpan(sizeSpan, start, end, flag)
if (moreSpanClickEnable) {
spannableString.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
ds.isUnderlineText = false
}
override fun onClick(widget: View) {
onTextClickListener?.onClick(widget)
}
}, 0, start - 1, flag)
//设置 More Text 点击
spannableString.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
ds.isUnderlineText = false
}
override fun onClick(widget: View) {
onSpanClickListener?.invoke(showState)
if (shouldAutoExpand) {
maxLines = Int.MAX_VALUE
text = getOriginContentText()
showState = ShowState.EXPAND
seeLess()
}
}
}, start, end - 1, flag)
movementMethod = LinkMovementMethod.getInstance()
}
setText(spannableString, BufferType.SPANNABLE)
}
fun setTextClickListener(onClickListener: OnClickListener) {
onTextClickListener = onClickListener
}
@SuppressLint("ResourceType")
private fun seeLess() {
if (seeLessEnable) {
val start = getOriginContentText().length + 1
val end = getOriginContentText().length + seeLessText.length + 1
val flag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
val text = SpannableStringBuilder(getOriginContentText()).append(" $seeLessText")
val spannableString = SpannableString(text)
//设置字体大小
val sizeSpan = AbsoluteSizeSpan(floor(seeLessTextSize).toInt())
spannableString.setSpan(sizeSpan, start, end, flag)
if (lessSpanClickEnable) {
//设置点击
spannableString.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
ds.isUnderlineText = false
}
override fun onClick(widget: View) {
maxLines = maxShowLine
firstDraw = true
setText(getOriginContentText())
showState = ShowState.SHRINK
onSpanClickListener?.invoke(showState)
}
}, start, end - 1, flag)
//设置字体颜色
val colorSpan = ForegroundColorSpan(seeLessTextColor!!)
spannableString.setSpan(colorSpan, start, end, flag)
movementMethod = LinkMovementMethod.getInstance()
}
setText(spannableString, BufferType.SPANNABLE)
}
}
/**
* 当调用了show函数才生效,不调用和TextView相同
*/
fun showText(text: CharSequence, urlClickBlock: ((url: String) -> Unit)? = null) {
this.originContentText = text
// 处理spanned的url点击事件
if (text is Spanned) {
// Create a new SpannableString from the Spanned object
val spannableString = SpannableStringBuilder(text)
// Copy existing spans to the new SpannableString
val spans = text.getSpans(0, text.length, Any::class.java)
for (span in spans) {
val start = text.getSpanStart(span)
val end = text.getSpanEnd(span)
val flags = text.getSpanFlags(span)
spannableString.setSpan(span, start, end, flags)
}
// Find any existing URLSpan objects
val urlSpans = spannableString.getSpans(0, spannableString.length, URLSpan::class.java)
if (urlSpans.isNotEmpty() && urlClickBlock != null) {
movementMethod = LinkMovementMethod.getInstance()
}
// Replace each URLSpan with our custom ClickableSpan
urlSpans.forEach { oldSpan ->
val start = spannableString.getSpanStart(oldSpan)
val end = spannableString.getSpanEnd(oldSpan)
// Remove the existing URLSpan
spannableString.removeSpan(oldSpan)
// Create a new custom ClickableSpan
val clickable = object : ClickableSpan() {
override fun onClick(view: View) {
// Pass the URL to the provided onUrlClick function
urlClickBlock?.invoke(oldSpan.url)
}
override fun updateDrawState(textPaint: TextPaint) {
super.updateDrawState(textPaint)
// Apply the custom link color and remove the underline
textPaint.color =
ContextCompat.getColor(context, android.R.color.holo_blue_dark)
textPaint.isUnderlineText = false
}
}
// Apply the new ClickableSpan to the SpannableString
spannableString.setSpan(clickable, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
this.originContentText = spannableString
}
maxLines = maxShowLine
firstDraw = true
needFold = false
setText(getOriginContentText())
}
fun setAutoExpandSeeMore(auto: Boolean): MoreLessRichTextView {
this.shouldAutoExpand = auto
return this
}
/**
* 设置是否显示see more
*/
fun setSeeMoreEnable(enable: Boolean): MoreLessRichTextView {
this.seeMoreEnable = enable
return this
}
/**
* 设置是否显示see less
*/
fun setSeeLessEnable(enable: Boolean): MoreLessRichTextView {
this.seeLessEnable = enable
return this
}
/**
* 设置see more字体颜色
*/
fun setSeeMoreTextColor(@ColorRes color: Int): MoreLessRichTextView {
this.seeMoreTextColor = resources.getColor(color)
return this
}
/**
* 设置see more字体颜色
*/
fun setSeeLessTextColor(@ColorRes color: Int): MoreLessRichTextView {
this.seeLessTextColor = resources.getColor(color)
return this
}
/**
* 设置see More字号(SP)
*/
@JvmName("setSeeMoreTextSize1")
fun setSeeMoreTextSize(sp: Float): MoreLessRichTextView {
this.seeMoreTextSize = sp.dp
return this
}
/**
* 设置see More字号(SP)
*/
@JvmName("setSeeLessTextSize1")
fun setSeeLessTextSize(sp: Float): MoreLessRichTextView {
this.seeLessTextSize = sp.dp
return this
}
/**
* 设置see more提示语
*/
fun setSeeMoreText(seeMoreText: String): MoreLessRichTextView {
this.seeMoreText = seeMoreText
return this
}
/**
* 设置see more提示语
*/
fun setSeeLessText(seeMoreText: String): MoreLessRichTextView {
this.seeLessText = seeMoreText
return this
}
/**
* 设置最大显示行数,超过该行数折叠
*/
fun setMaxShowLine(maxLine: Int): MoreLessRichTextView {
this.maxShowLine = maxLine
return this
}
/**
* 设置当前显示状态:SHRINK(缩进) or EXPAND(展开), 默认SEE MORE
*/
fun setShowState(showState: ShowState): MoreLessRichTextView {
this.showState = showState
return this
}
/**
* 设置more span是否可点击
*/
fun setMoreSpanClickEnable(enable: Boolean): MoreLessRichTextView {
this.moreSpanClickEnable = enable
return this
}
/**
* 设置less span是否可点击
*/
fun setLessSpanClickEnable(enable: Boolean): MoreLessRichTextView {
this.lessSpanClickEnable = enable
return this
}
fun setTripleDotShow(enable: (maxShowLine: Int) -> Boolean): MoreLessRichTextView {
this.setTripleDotShowEnable = enable
return this
}
/**
* 获取当前显示状态:SHRINK(缩进) or EXPAND(展开), 默认SEE MORE
*/
fun getShowState(): ShowState {
return showState
}
@Keep
enum class ShowState {
SHRINK,
EXPAND
}
}
使用:
class TextViewFollowActivity : AppCompatActivity(), OnClickableSpanListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_text_view_follow)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val tvNormal = findViewById<TextView>(R.id.tv_normal)
val span = getSpanText(tvNormal, this)
tvNormal.text = span
findViewById<MoreLessRichTextView>(R.id.tv_more_less0).apply {
setMaxShowLine(2)
setSeeMoreEnable(true)
setSeeLessEnable(true)
setSeeMoreText("展示")
setSeeLessText("收起")
setSeeMoreTextColor(android.R.color.holo_red_dark)
setSeeLessTextColor(android.R.color.holo_blue_dark)
val text =
"1这是没有富文本的测试的,2这是没有富文本的测试的,3这是没有富文本的测试的,4这是没有富文本的测试的,5这是没有富文本的测试的,6这是没有富文本的测试的,7这是没有富文本的测试的,8这是没有富文本的测试的,9这是没有富文本的测试的,10这是没有富文本的测试的,11这是没有富文本的测试的。"
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less).apply {
setSeeMoreEnable(true)
setMaxShowLine(1)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setSeeLessTextColor(android.R.color.holo_blue_dark)
setSeeMoreText("展示")
setSeeLessText("收起")
val text = getSpanText(this, this@TextViewFollowActivity)
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less1).apply {
setSeeMoreEnable(true)
setMaxShowLine(2)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setSeeLessTextColor(android.R.color.holo_blue_dark)
setSeeMoreText("展示")
setSeeLessText("收起")
val text = getSpanText(this, this@TextViewFollowActivity)
text.append("这是2行的,这是2行的,这是2行的,这是2行的,这是2行的end")
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less2).apply {
setSeeMoreEnable(true)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setMaxShowLine(3)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setSeeLessTextColor(android.R.color.holo_blue_dark)
setSeeMoreText("展示")
setSeeLessText("收起")
val text = getSpanText(this, this@TextViewFollowActivity)
text.append("这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的end")
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_html).apply {
val longHtmlText =
"html这是3行的,<fon color=#FF00FF>这是3行的</font>,<font color=#A86104>哈哈哈哈</font>这是3行的,这是3行的,这是3行的,<strong>加重文本</strong> <em>强调文本</em>这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的,这是3行的end<strong>加重文本</strong> <em>强调文本</em> "
setSeeMoreEnable(true)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setMaxShowLine(3)
setSeeMoreTextColor(android.R.color.holo_red_dark)
setSeeLessTextColor(android.R.color.holo_blue_dark)
setSeeMoreText("展示")
setSeeLessText("收起")
showText(Html.fromHtml(longHtmlText))
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less_info).apply {
setMaxShowLine(1)
setSeeMoreEnable(true)
setSeeLessEnable(false)
setMoreSpanClickEnable(false)
setLessSpanClickEnable(false)
setSeeMoreText(">")
setTripleDotShow { maxShowLine ->
maxShowLine >= 3
}
val text = getSpanText2(this, this@TextViewFollowActivity)
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less_info2).apply {
setMaxShowLine(2)
setSeeMoreEnable(true)
setSeeLessEnable(false)
setMoreSpanClickEnable(false)
setLessSpanClickEnable(false)
setSeeMoreText(">")
setTripleDotShow { maxShowLine ->
maxShowLine >= 3
}
val text = getSpanText2(this, this@TextViewFollowActivity)
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less_info3).apply {
setMaxShowLine(3)
setSeeMoreEnable(true)
setSeeLessEnable(false)
setMoreSpanClickEnable(false)
setLessSpanClickEnable(false)
setSeeMoreText(">")
setTripleDotShow { maxShowLine ->
maxShowLine >= 3
}
val text = getSpanText2(this, this@TextViewFollowActivity)
showText(text)
}
findViewById<MoreLessRichTextView>(R.id.tv_more_less_info4).apply {
setMaxShowLine(5)
setSeeMoreEnable(true)
setSeeLessEnable(false)
setMoreSpanClickEnable(false)
setLessSpanClickEnable(false)
setSeeMoreText(">")
setTripleDotShow { maxShowLine ->
maxShowLine >= 5
}
val text = getSpanText2(this, this@TextViewFollowActivity)
showText(text)
}
}
private fun getSpanText2(
textview: TextView,
listener: OnClickableSpanListener
): SpannableStringBuilder {
val spanBuild = SimplifySpanBuild()
spanBuild
.append(
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.live_avatar_default)
)
.setGravity(SpecialGravity.CENTER)
)
.append("Hurry up!")
.append(
SpecialTextUnit("Cheaper than added").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(Color.BLUE)
).setTextColor(
Color.parseColor("#FA6338")
)
)
.append(
SpecialTextUnit("[括号内这是用来测试跨行的富文本显示的,颜色为红色]").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(Color.BLUE)
).setTextColor(Color.RED)
)
.append(
SpecialTextUnit("[括号内这是用来测试最后一行富文本的显示,哈哈哈哈哈哈哈,颜色为蓝色]").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(Color.BLUE)
).setTextColor(Color.BLUE)
)
.append(",up to \$10!up to \$1 up to \$10!up to \$10tup to o \$10up to \$10!up to \$1 up to \$10!up to \$10tup to o \$10up to \$10!up to \$1 up to \$10!up to \$10tup to o \$10up to \$10!up to \$1 up to \$10!up to \$10t up to o \$10!up to o \$10! up to o \$10! up to o \$10! up to o \$10! up to o \$10!")
return spanBuild.build()
}
private fun getSpanText(
textview: TextView,
listener: OnClickableSpanListener
): SpannableStringBuilder {
val linkNorTextColor = -0xb7c275
val linkPressBgColor = -0x783106
val spanBuild = SimplifySpanBuild()
spanBuild.append("无默认背景11]")
.append(
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.level)
)
.setGravity(SpecialGravity.CENTER)
)
.append(
SpecialTextUnit("[点我点我000").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(-0xb000)
).setTextColor(
Color.BLUE
)
)
.appendMultiClickable(
SpecialClickableUnit(textview, listener).setNormalTextColor(linkNorTextColor)
.setPressBgColor(linkPressBgColor),
" ",
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.level),
80,
50
)
.setGravity(SpecialGravity.CENTER),
SpecialTextUnit(" 用户名 ")
)
.append(
SpecialTextUnit("[点我点我1").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(-0xb000)
).setTextColor(
Color.BLUE
)
)
.append("哈哈哈")
.append(
SpecialTextUnit("[括号内测试富文本跨行显示,颜色红色]").setClickableUnit(
SpecialClickableUnit(
textview,
listener
).setTag("1").setPressBgColor(-0xb000)
).setTextColor(Color.RED)
)
.append("无默认背景显示下划线")
.append(
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.level)
)
.setGravity(SpecialGravity.CENTER)
)
.append(
SpecialTextUnit("点我点我2").setClickableUnit(
SpecialClickableUnit(textview, listener).setTag("2").showUnderline()
.setPressBgColor(-0xb000).setPressTextColor(
Color.WHITE
)
).setTextColor(-0xb000)
)
.append("有默认背景")
.append(
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.level),
120,
120
)
.setGravity(SpecialGravity.CENTER)
)
.append(
SpecialTextUnit("点我点我3").setClickableUnit(
SpecialClickableUnit(textview, listener).setTag("3").setPressBgColor(
Color.BLUE
).setPressTextColor(Color.WHITE)
).setTextColor(-0xb000).setTextBackgroundColor(-0x783115)
)
.append(
SpecialImageUnit(
applicationContext,
BitmapFactory.decodeResource(resources, R.drawable.level),
180,
180
)
.setGravity(SpecialGravity.CENTER)
)
.append("我只是个结尾")
return spanBuild.build()
}
override fun onClick(tv: TextView?, clickableSpan: CustomClickableSpan?) {
Log.d("hacket", "onClick, tv=$tv, clickableSpan=$clickableSpan")
toast("onClick, tv=$tv, clickableSpan=$clickableSpan")
}
}
效果:
