Android 富文本 点击变色、事件传递

开发语言为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()
}

注释应该够了,可有帮助?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值