昨天总结了下 SpannableString 的用法,在学习之后发现 SpannableString 还是能干很多事的,我的印象里记得 SpannableString 也就是能改个颜色,改个大小。所以这次看完也不知道记忆能保鲜多久,怕忘,想了想还是写个小工具好些,一是加强印象,这写和不写完全是2个概念,二是以后也方便用
项目地址:BW_Libs
Snip20180910_4.png代码设计
- 首先像 SpannableString 这种功能单一,类很少的,只能成为 utils 工具,而不能叫 lib 库的,所以起名就叫 SpanUtils 好了
SpanUtils
.with(tx01)
.foregroundColor(Color.BLUE, tx01.text.indexOf("-") + 1, tx01.text.length)
.show()
- 工具类一般都需要有统一的入口的,所以我们使用 kotlin + 静态单例的方式来提供工具使用规范。为了赶上链式调用的春风,可以不停的 . 下去,所以我们就不能直接返回 SpannableString 对象了,而是我们写的 SpannableString 功能包装类。开始的资源绑定方法,我们提供2个重载,可以接受 String 和 TextView
companion object {
fun with(text: String): SpanUtils {
return SpanUtils(text)
}
fun with(textView: TextView): SpanUtils {
return SpanUtils(textView, textView.text.toString())
}
}
- 最后我们也提供显示的重载,除了可以使用已经绑定的 TextView 外,也可以指定 TextView,
fun show() {
textView?.setText(spannable)
}
fun show(textView: TextView?) {
textView?.setText(spannable)
}
- 然后我们再提供获取最终的 String 和 SpannableString 的方法
fun getString(): String {
return spannable.toString()
}
fun getSpannableString(): SpannableString {
return spannable
}
- 这样的话这个小工具基本就齐活了,在使用上也能做到比较灵活了。我一直觉得小的进步积累多了之后就是巨大的改变,这样的技术进步才是最稳的,不知不觉的我们就可以写出不错的能看的工具,库,组件出来了。
最后代码
class SpanUtils(text: String) {
// SpannableString 文字样式对象
lateinit var spannable: SpannableString
// 关联的 view
var textView: TextView? = null
companion object {
/**
* 全局静态入口
*/
fun with(text: String): SpanUtils {
return SpanUtils(text)
}
/**
* 全局静态入口
*/
fun with(textView: TextView): SpanUtils {
return SpanUtils(textView, textView.text.toString())
}
}
/**
* 主构造函数里,初始化 SpannableString 对象
*/
init {
this.spannable = SpannableString(text)
}
constructor(textView: TextView, text: String) : this(text) {
this.textView = textView
}
/**
* 返回最终结果
*/
fun getString(): String {
return spannable.toString()
}
/**
* 返回最终结果
*/
fun getSpannableString(): SpannableString {
return spannable
}
/**
* 显示
*/
fun show() {
textView?.setText(spannable)
}
/**
* 显示
*/
fun show(textView: TextView?) {
textView?.setText(spannable)
}
/**
* 添加前景色
*/
fun foregroundColor(color: Int, startIndex: Int, endIndex: Int): SpanUtils {
var forColorSpan = ForegroundColorSpan(color)
spannable.setSpan(forColorSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 添加前景色
*/
fun backgroundColor(color: Int, startIndex: Int, endIndex: Int): SpanUtils {
var backColorSpan = BackgroundColorSpan(color)
spannable.setSpan(backColorSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 相对文字大小
* size: 应使用诸如 1.2F 这样的参数格式
*/
fun relativeTextSize(size: Float, startIndex: Int, endIndex: Int): SpanUtils {
var relativeSizeSpan = RelativeSizeSpan(size)
spannable.setSpan(relativeSizeSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 绝对文字大小
* size: 应使用 sp 转换成的 int 值
*/
fun absoluteTextSize(size: Int, startIndex: Int, endIndex: Int): SpanUtils {
var absoluteSizeSpan = AbsoluteSizeSpan(size)
spannable.setSpan(absoluteSizeSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 中划线
*/
fun middleLine(startIndex: Int, endIndex: Int): SpanUtils {
var strikethroughSpan = StrikethroughSpan()
spannable.setSpan(strikethroughSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 下划线
*/
fun underLine(startIndex: Int, endIndex: Int): SpanUtils {
var underLineSpan = UnderlineSpan()
spannable.setSpan(underLineSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 上标
* 请允许我使用自创单词,因为原生单词实在不好记忆,也容易和下标混淆
*/
fun topFlag(startIndex: Int, endIndex: Int): SpanUtils {
var superscriptSpan = SuperscriptSpan()
spannable.setSpan(superscriptSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 下标
* 请允许我使用自创单词,因为原生单词实在不好记忆,也容易和上标混淆
*/
fun bottomFlag(startIndex: Int, endIndex: Int): SpanUtils {
var subscriptSpan = SubscriptSpan()
spannable.setSpan(subscriptSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 粗体
*/
fun bold(startIndex: Int, endIndex: Int): SpanUtils {
var boldSpan = StyleSpan(Typeface.BOLD)
spannable.setSpan(boldSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 斜体
*/
fun italic(startIndex: Int, endIndex: Int): SpanUtils {
var italicSpan = StyleSpan(Typeface.ITALIC)
spannable.setSpan(italicSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 斜粗体
*/
fun italicAndBlod(startIndex: Int, endIndex: Int): SpanUtils {
var italicAndBlodSpan = StyleSpan(Typeface.BOLD_ITALIC)
spannable.setSpan(italicAndBlodSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 斜粗体
* drawable: 图片必须显示的指名大小,才能有效显示,请参考 - drawable.setBounds(0, 0, 80, 80)
*/
fun image(drawable: Drawable, startIndex: Int, endIndex: Int): SpanUtils {
var imageSpan = ImageSpan(drawable)
spannable.setSpan(imageSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
return this@SpanUtils
}
/**
* 可点击区域
* textView: 必须设置 setMovementMethod() 方法才能实现点击
*/
fun clickable(textView: TextView, ClickableSpan: ClickableSpan, startIndex: Int, endIndex: Int): SpanUtils {
spannable.setSpan(ClickableSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
textView.setMovementMethod(LinkMovementMethod.getInstance())
return this@SpanUtils
}
/**
* 超链接
* adress: 必须加 http:// 协议才能正常跳转到系统浏览器
*/
fun url(textView: TextView, adress: String, startIndex: Int, endIndex: Int): SpanUtils {
var urlSpan = URLSpan(adress)
spannable.setSpan(urlSpan, startIndex, endIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
textView.setMovementMethod(LinkMovementMethod.getInstance())
return this@SpanUtils
}
}
网友评论