Android Span富文本自定义垂直对齐样式 - ReplacementSpan
程序员文章站
2022-03-04 09:07:26
###最近有个需求要实现这样的效果:&可能会想先Span改变字体大小,然后对齐方式设置:Top;然而尝试后并不行...so...#1 直接上效果:cc:我们默认情况下是向下对齐,我们需要自定义来改成对齐方式:#2自定义SuperSubSpan:class SuperSubSpan(private val type: SubSpanType = SubSpanType.DEFAULT) : ReplacementSpan() { override fun.....
###有个需求要实现这样的效果:
这个时候,有写过添加上下标,这样就很好实现:我是传送门
#效果:
#简单贴上代码:
private fun getSuperscriptSpanShow(): Spannable {
val indexTH = TEXT_DATE.indexOf(TEXT_TH)
val sb = SpannableStringBuilder(TEXT_DATE)
//先更改TH的文本
sb.setSpan(
TextAppearanceSpan(this, R.style.DateTextTH),
indexTH,
indexTH + TEXT_TH.length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
//将TH作为上标
sb.setSpan(
SuperscriptSpan(),
indexTH,
indexTH + TEXT_TH.length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
return sb
}
以上可以完全实现,如果要实现垂直对齐居中,好像就很麻烦了
&可能会想先Span改变字体大小,然后对齐方式设置:Center;然而尝试后并不行...
so...
#1 直接上效果:
cc:默认情况下是向下对齐,这里就需要自定义对齐方式
#2 自定义ReplacementSpan:
class SuperSubSpan(private val type: SubSpanType = SubSpanType.DEFAULT) : ReplacementSpan() {
override fun getSize(
paint: Paint,
text: CharSequence,
start: Int,
end: Int,
fm: Paint.FontMetricsInt?
): Int {
val subText = text.subSequence(start, end)
return paint.measureText(subText.toString()).toInt()
}
override fun draw(
canvas: Canvas,
text: CharSequence,
start: Int,
end: Int,
x: Float,
top: Int,
y: Int,
bottom: Int,
paint: Paint
) {
val subText = text.subSequence(start, end)
val fm = paint.fontMetricsInt
val subY = when (type) {
SubSpanType.CENTER -> {
(fm.descent - fm.ascent) + (y - (fm.descent - fm.ascent)) / 2
}
SubSpanType.TOP -> {
fm.descent - fm.ascent
}
SubSpanType.DEFAULT -> {
y
}
}
canvas.drawText(subText.toString(), x, subY.toFloat(), paint)
}
}
补充下:定义几个垂直方向的对齐类型
enum class SubSpanType {
DEFAULT,
TOP,
CENTER
}
cc:这里只是改变垂直对齐方式,并没有把字体,大小,颜色等封装进来。
#3 简单使用:
sb.setSpan(SuperSubSpan(type),startIndex, endIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
#4 Activity/Fragment 举例:
class MainActivity : AppCompatActivity() {
companion object {
private const val TEXT_DATE = "Jul 25th, 11:11am"
private const val TEXT_TH = "th"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}
private fun initView() {
//Jul 23th
text_sub_default.text = getDateSpanShow(SubSpanType.DEFAULT)
text_sub_top.text = getDateSpanShow(SubSpanType.TOP)
text_sub_center.text = getDateSpanShow(SubSpanType.CENTER)
}
private fun getDateSpanShow(type: SubSpanType): Spannable{
val indexTH = TEXT_DATE.indexOf(TEXT_TH)
val sb = SpannableStringBuilder(TEXT_DATE)
sb.setSpan(
TextAppearanceSpan(this, R.style.DateTextTH),
indexTH,
indexTH + TEXT_TH.length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
sb.setSpan(
SuperSubSpan(type),
indexTH,
indexTH + TEXT_TH.length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
return sb
}
}
以上就是 自定义对齐样式的 简单 实现!!!
###另外简单介绍下Spanable中的常用常量:
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE -- 不包含start和end所在的端点 (a,b)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE -- 不包含端start,但包含end所在的端点 (a,b]
Spanned.SPAN_INCLUSIVE_EXCLUSIVE -- 包含start,但不包含end所在的端点 [a,b)
Spanned.SPAN_INCLUSIVE_INCLUSIVE -- 包含start和end所在的端点 [a,b]
Spanable...
本文地址:https://blog.csdn.net/qq_20613731/article/details/107476774