昨天總結了下 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
}
}