市面同类型框架只是使用链式编程简化了下方法调用且限制住了官方方法
但富文本基本上是占位符或者拼接字符串, 所以期望是能像字符串一样拼接Span和正则替换
这里就推荐Spannable的扩展库: spannable
实现效果预览
为了通用性函数全部使用的CharSequence接口, 使用起来和字符串没有区别
可以设置/插入/添加来构建Span
// 通过拼接方式展示价格
tv5.text = "¥".setSpan(ColorSpan("#ed6a2c"))
.addSpan("39.9", arrayOf(ColorSpan("#ed6a2c"), AbsoluteSizeSpan(18, true)))
.addSpan(" 1000+ 人付款")
.addSpan("image", CenterImageSpan(this, R.drawable.ic_touch).setDrawableSize(20, dp = true))
复制代码
可以像string一样使用文字替换/正则匹配创建样式
tv.movementMethod = ClickableMovementMethod.getInstance()
tv.text = "隐私权政策 | 许可 | 品牌指南".replaceSpan("隐私权政策") {
URLSpan("https://github.com/") // 仅替换效果
}
tv.text = "隐私权政策 | 许可 | 品牌指南".replaceSpan("隐私权政策") {
listOf(URLSpan("https://github.com/"), ColorSpan("#ed6a2c")) // 替换多个效果
}
tv.text = "隐私权政策 | 许可 | 品牌指南".replaceSpan("隐私权政策") {
SpannableString("友情链接").setSpan(URLSpan("https://github.com/")) // 替换文字以及Span效果
}
// 还可以使用正则替换
tv2.text = "我们可以艾特用户@用户昵称 或者创建#热门标签"
.replaceSpan("@[^@]+?(?=\\s|\$)".toRegex()) { matchResult ->
HighlightSpan("#ed6a2c") {
Toast.makeText(this@MainActivity, "点击用户 ${matchResult.value}", Toast.LENGTH_SHORT).show()
}
}
// 通过丰富的正则/匹配功能你可以快速渲染占位符富文本
tv2.text = "当前货币单位为{{美元}}".replaceSpan("{{美元}}"){
CenterImageSpan(context, R.drawable.ic_dollar) // 将占位图替换成图片
}
复制代码
由于所有函数返回值和接受者都是CharSequence你甚至可以封装到一个函数中复用一组Span规则, 比如实现直播间消息/评论内容/简单的富文本输入框
函数
使用的函数一定要非常简单
函数 | 介绍 |
---|---|
setSpan | 设置Span |
addSpan | 添加/插入Span或字符串 |
replaceSpan | 替换/正则替换Span或字符串 |
replaceSpanFirst/replaceSpanLast | 替换/正则替换第一个/最后一个匹配项的Span或字符串 |
市面上大多是使用链式编程拼接Span我觉得扩展性极差而且为了节省几个单词就造一堆函数增加学习成本 如果你喜欢DSL或者链式编程可以使用其他作者的分叉版本:SpannableX
并包含一些常用的Span效果实现, 欢迎贡献自己的
Span | 描述 |
---|---|
CenterImageSpan | 垂直对齐方式/图片宽高/固定图片比例 |
GlideImageSpan | 加载网络图片/垂直对齐方式/图片宽高/固定图片比例 |
ColorSpan | 快速创建文字颜色 |
HighlightSpan | 创建字体颜色/字体样式/可点击效果 |
ClickableMovementMethod | 等效LinkMovementMethod, 但没有点击背景色 |
官方只提供ImageSpan, 且垂直对齐还要求api23以上, 而且无法指定宽度所以提供了两个新的ImageSpan
CenterImageSpan 支持图片宽高指定, 且缩放不会导致图片拉伸. 垂直居中对齐方式, 自适应高度
GlideImageSpan则支持下载图片以及使用Glide进行更自定义的图片加载选项(比如裁剪/圆角/占位图)