android 自定义span_Android Span富文本自定义垂直对齐样式 - ReplacementSpan

这篇博客介绍了如何在Android中自定义`ReplacementSpan`实现文本的垂直对齐,包括顶部、中心和默认对齐。通过创建`SuperSubSpan`类并结合`TextAppearanceSpan`,可以为日期中的特定部分(如`th`)设置不同的对齐样式。博客还提到了`Spannable`中的常用常量及其含义。
摘要由CSDN通过智能技术生成

###有个需求要实现这样的效果:

这个时候,有写过添加上下标,这样就很好实现:我是传送门

#效果:

#简单贴上代码:

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值