開發語言為Kotlin,還在使用java的小朋友,不妨試試
在android中富文本的使用近乎頻繁了,網上資料頗多,手上剛好在做一個帶有圈子子產品的項目
貼代碼:
自定義類 DefaultClickSpan.kt
import android.support.v4.content.ContextCompat
import android.text.TextPaint
import android.text.style.ClickableSpan
import android.view.View
import android.widget.TextView
import com.qiufeng.educationteacher.R
import com.qiufeng.educationteacher.application.App
import com.qiufeng.educationteacher.ui.listener.ClickListener
import io.reactivex.Flowable
import java.util.concurrent.TimeUnit
class DefaultClickSpan(
val params: Any? = null,
val listener: ClickListener? = null,
val color: Int = -1
) : ClickableSpan() {
override fun updateDrawState(ds: TextPaint?) {
super.updateDrawState(ds)
ds?.let {
// 點選文本顔色
it.color = RUtils.getColor(if (color == -1) R.color.color_blue_grey else color)
// 去除下劃線
it.isUnderlineText = false
}
}
override fun onClick(widget: View?) {
widget?.let {
if (it is TextView) {
// 點選時,被點選區域的背景色
it.highlightColor = RUtils.getColor(R.color.color_grey)
// 啟動一個延時任務,200毫秒後恢複區域顔色
Flowable.timer(200, TimeUnit.MILLISECONDS).doOnComplete {
(widget as TextView).highlightColor = RUtils.getColor(R.color.color_transparent)
}.subscribe()
}
// 點選區域時需要傳遞的參數
if (params != null && listener != null) {
listener.onClick(params)
}
}
}
}
點選事件監聽 ClickListener.kt
interface ClickListener {
fun onClick(any:Any)
}
工具類 RUtils.kt
class RUtils {
companion object {
/**
* 擷取資源顔色色值
* @param rId
*/
fun getColor(rId: Int): Int {
return ContextCompat.getColor(App.context, rId)
}
}
}
Span工具類:SpannedUtils.kt
class SpannedUtils {
companion object {
/**
* 拼接點選Span
* @param sb 拼接源
* @param clickStr 需要拼接的點選文字
* @param params 點選事件響應傳回的資料
* @param color 拼接字元的前景色
* @param clickListener 點選事件監聽
*/
fun appendClickableSpan(sb: SpannableStringBuilder,
clickStr: String,
params: Any? = null,
color: Int = -1,
clickListener: ClickListener? = null) {
val oldLength = sb.length
sb.append(clickStr)
sb.setSpan(DefaultClickSpan(params, clickListener, color), oldLength, sb.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
前端頁面調用(使用資料為類似點贊人清單)
private fun setText(list:MutableList<String>){
val sb = SpannableStringBuilder()
val length = list.size
(0 until length){
SpannedUtils.appendClickableSpan(sb,list[it],list[it],object:ClickListener{
override fun onClick(any: Any) {
showToast(any.toString())
}
})
}
// 顔色、回傳參數、監聽可以不加
// SpannedUtils.appendClickableSpan(sb,list[it])
tvHeart.text = sb
// 這句很重要,否則點選無效
tvHeart.movementMethod = LinkMovementMethod.getInstance()
}
發現一個重要問題:
在設定點選事件的時候,如果涉及到頁面的跳轉等UI操作,可能會産生一個bug:
Only the original thread that created a view hierarchy can touch its views
錯誤提示:(有道詞典)隻有建立了視圖層次結構的原始線程才能通路它的視圖;跨線程修改UI的問題
解決: 修改DefaultClickSpan類
将點選事件做一下延遲就好,可以用上面的Flowable.timer,延遲事件跟 恢複背景色的時間一緻就可以
// 部分代碼
if (params != null && listener != null) {
Flowable.timer(200, TimeUnit.MILLISECONDS)
.doOnComplete {
listener.onClick(params)
}.subscribe()
}
注釋應該夠了,可有幫助?