android TextView 实现富文本显示

android TextView 实现富文本显示,实现抖音直播间公屏消息案例

使用:

val tvContent: TextView = helper.getView(R.id.tvContent)


//自己根据UI业务要求,可以控制 图标显示 大小
 val levelLabel = MyImgLabel( bitmap = 自己业务上的bitmap  )

 val labelNickName = MyLabel(
                title = "昵称",
                color = 自己给个颜色,
                myLabelClick = object : MyLabelClick {
                    override fun click() {
                        //点击了昵称事件
                    }
                })

  val labelContent = MyLabel(
                title = "消息内容",
                color = 自己给个颜色
            )

 tvContent.setMySpannable(levelLabel, labelNickName, labelContent)

 //如果需要显示多个 图标 imgLabelxxx 是 MyImgLabel
 //MyLabel 与 MyImgLabel 摆放位置是根据自己的业务需求 摆放的,这只是个例子
tvContent.setMySpannable(levelLabel, labelNickName, imgLabelxxx,labelContent,imgLabelxxx)

代码

/**
 * 点击事件
 */
interface  MyLabelClick{
    fun click()
}

  文本标签 

open class MyLabel(
    var title:String,
    var textStyleIsBold:Boolean? = false, //字体是否加粗
    @ColorInt var color:Int,
    var myLabelClick: MyLabelClick?=null
)

图标标签

class MyImgLabel(
    var bitmap:Bitmap,
    var imgLabelClick: MyLabelClick? = null
) : MyLabel(title = "level", color = 0, myLabelClick = imgLabelClick)

 自定义 ImageSpan 

class CenteredImageSpan : ImageSpan {

    constructor(context: Context, drawableRes: Int) : super(context, drawableRes) {}
    constructor(context: Context, bitmap: Bitmap) : super(context, bitmap) {}

    override fun draw(
        @NonNull canvas: Canvas, text: CharSequence?,
        start: Int, end: Int, x: Float,
        top: Int, y: Int, bottom: Int, @NonNull paint: Paint
    ) {
        val b: Drawable = getDrawable()
        val fm: Paint.FontMetricsInt = paint.getFontMetricsInt()
        val transY: Int = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2 //计算y方向的位移
        canvas.save()
        canvas.translate(x, transY.toFloat()) //绘制图片位移一段距离
        b.draw(canvas)
        canvas.restore()
    }
}

 代码块


fun MyLabel.setSpannableColorAndClick(spannableString: SpannableString, myLabel: MyLabel, startIndex:Int, endIndex:Int){

    spannableString.setSpan(object: ClickableSpan(){
        override fun onClick(widget: View) {
            LogUtils.d("点击事件")
            myLabel.myLabelClick?.click()

        }
        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.color = myLabel.color
            //取消默认的下划线
            ds.isUnderlineText = false
        }
    },startIndex,endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)


}

fun TextView.setMySpannable(spannableString: SpannableString){
    text = spannableString
    //中途遇到点击后字体显示高亮,取消高亮
    highlightColor = Color.parseColor("#00000000")
    //最后设置可点击,必须实现,否则只能显示样式,无法实现点击效果
    movementMethod = LinkMovementMethod.getInstance()
}

fun TextView.setMySpannable(vararg myLabels: MyLabel?){

    text = getMySpannableString(context,*myLabels)
    //中途遇到点击后字体显示高亮,取消高亮
    highlightColor = Color.parseColor("#00000000")
    //最后设置可点击,必须实现,否则只能显示样式,无法实现点击效果
    movementMethod = LinkMovementMethod.getInstance()
}

private fun getMySpannableString(context: Context,vararg myLabels: MyLabel?):SpannableString{

    //step1:得到全部显示的内容
    var msgContent = StringBuffer()

    val indexMap:MutableMap<Int,Int> = mutableMapOf()

    var startIndex = 0
    myLabels?.forEachIndexed { index, myLabel ->
        if (myLabel!= null){
            msgContent.append(myLabel.title)
            indexMap[index] =startIndex
            startIndex += myLabel.title.length
        }

    }
    val spannableString = SpannableString(msgContent)

    log("spannableString:${spannableString}")
    //step2:设置颜色以及点击事件
    myLabels?.forEachIndexed { index, myLabel ->

        if (myLabel!= null){
            val startIndex = indexMap[index]
            val endIndex = startIndex?.plus(myLabel.title.length)

            if (myLabel is MyImgLabel){
                //要让图片替代指定的文字就要用ImageSpan
                val imageSpan = myLabel.bitmap?.let {
                    CenteredImageSpan(context, it)
                }

                spannableString.setSpan(imageSpan, startIndex!!, endIndex!!, ImageSpan.ALIGN_BASELINE)
            }else{
                if (myLabel.textStyleIsBold == true){
                    val styleSpan = StyleSpan(Typeface.BOLD)
                    spannableString.setSpan(styleSpan,startIndex!!, endIndex!!,Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
                }
            }
            myLabel.setSpannableColorAndClick(
                spannableString= spannableString,
                myLabel =myLabel,
                startIndex = startIndex!!,
                endIndex = endIndex!!
            )
        }

    }

    return spannableString
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/419753.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

卷积神经网络基本概念补充

卷积&#xff08;convolution&#xff09;、通道&#xff08;channel&#xff09; 卷积核大小一般为奇数&#xff0c;有中心像素点&#xff0c;便于定位卷积核。 步长&#xff08;stride&#xff09;、填充&#xff08;padding&#xff09; 卷积核移动的步长&#xff08;stride…

FPGA之带有进位逻辑的加法运算

module ADDER&#xff08; input [5&#xff1a;0]A&#xff0c; input [5&#xff1a;0]B&#xff0c;output[6&#xff1a;0]Q &#xff09;&#xff1b; assign Q AB&#xff1b; endmodule 综合结果如下图所示&#xff1a; 使用了6个Lut&#xff0c;&#xff0c;6个LUT分布…

定制红酒:一次满足需求的个性化服务体验

云仓酒庄洒派提供一次满足需求的个性化服务体验&#xff0c;让您的红酒定制之旅成为一段美好的记忆。 首先&#xff0c;云仓酒庄洒派深入了解每位消费者的需求。无论是对于红酒品种、年份、外包装还是其他个性化要求&#xff0c;云仓酒庄洒派都认真倾听并记录下来。这种细致入微…

Solo 开发者周刊 (第6期):

这里会整合 Solo 社区每周推广内容、产品模块或活动投稿&#xff0c;每周五发布。在这期周刊中&#xff0c;我们将深入探讨开源软件产品的开发旅程&#xff0c;分享来自一线独立开发者的经验和见解。本杂志开源&#xff0c;欢迎投稿。 产品推荐 1. 助眠类播客《静夜斋》上线 一…

echarts鼠标向右/向左绘制实现放大/还原

echarts toolbox 的datazoom提供了绘制放大的功能&#xff0c;但通过鼠标绘制只能进行放大 应需求放大与还原都通过鼠标行为实现&#xff0c;增加从右往左绘制时还原放大结果 demo 结果 重写datazoom的原型方法实现绘制事件的拦截 const comp myChart._model.getComponent(to…

typora激活破解——仅需修改js即可

先打开官网下载typora&#xff0c;typora官网地址&#xff1a;https://typoraio.cn/安装完成后先启动一次Typora&#xff0c;看到激活提示&#xff0c;不需要点试用&#xff0c;直接关闭软件即可。找到安装路径&#xff0c;一般在 C:\Program Files接着找到安装路径&#xff0c…

CC攻击与DDoS攻击有什么区别?如何进行有效防护?

CC攻击的前身是一个名为Fatboy攻击程序&#xff0c;而之所以后来人们会成为CC&#xff0c;是因为DDoS攻击发展的初期阶段&#xff0c;绝大部分DDoS攻击都能被业界熟知的“黑洞”&#xff08;collapsar&#xff0c;一种安全防护产品&#xff09;所抵挡&#xff0c;CC攻击的诞生就…

配置artifactory的反向代理和域名访问

一、概述 在许多情况下&#xff0c;组织会通过反向代理来提供对 Artifactory 的访问。在某些情况下&#xff0c;例如使用 Artifactory 作为 Docker 注册表&#xff0c;这种设置甚至是强制性的。为了简化反向代理的配置&#xff0c;Artifactory 提供了生成反向代理的功能&#x…

android开发需要哪些基础,已拿到offer

在线绘图神器 很多小伙伴咨询说博客文章里的技术图怎么画出来的&#xff0c;这里透个底&#xff0c;大部分都是通过processon画出来的&#xff0c;在线画图十分方便&#xff0c;几乎可以画出你想要的任何技术图&#xff0c;包括&#xff1a;流程图、思维导图、原型图、UML图、…

WEB漏洞 逻辑越权之支付数据篡改安全

水平越权 概述&#xff1a;攻击者尝试访问与他拥有相同权限的用户的资源 测试方法&#xff1a;能否通过A用户操作影响到B用户 案例&#xff1a;pikachu-本地水平垂直越权演示-漏洞成因 1&#xff09;可以看到kobe很多的敏感信息 2&#xff09;burp抓包&#xff0c;更改user…

Unity中URP实现水体(整理优化)

文章目录 前言一、优化水的深度1、我们把 水流动的方向 和 水深浅过渡值&#xff0c;整合到一个四维变量中2、修改 水体流动方向3、在片元着色器中&#xff0c;修改使用过渡变量 二、优化泡沫三、优化水下的扭曲1、修复原本扰动UV的计算 四、优化水面高光1、把高光强度、光滑度…

基于java+springboot景区行李寄存管理系统设计和实现

基于javaspringboot景区行李寄存管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取…

今年国内石油需求稳中有升,巡检机器人助力石油行业可持续发展

前言&#xff1a;全球能源市场出现普遍回落趋势&#xff0c;其中石油价格下降近20%&#xff0c;而天然气和煤炭价格更是下跌超过50%。此外&#xff0c;碳酸锂和光伏组件价格也纷纷下降超过50%。这种价格下滑对于全球经济的持续增长&#xff0c;尤其是控制通货膨胀方面&#xff…

OpenLayers线性渐变和中心渐变(径向渐变)

目录 1.前言2.添加一个面要素3.线性渐变3.1 第一个注意点3.2 第二个注意点 4.中心渐变&#xff08;径向渐变&#xff09;5.总结 1.前言 OpenLayers官网有整个图层的渐变示例&#xff0c;但是没有单个要素的渐变示例&#xff0c;我们这里来补充一下。OpenLayers中的渐变是通过fi…

创意电子名片二维码生成的优势:引领商务交流的全新潮流

在数字化时代&#xff0c;传统的纸质名片已逐渐被创新的电子名片二维码所取代。电子名片生成二维码作为一种便捷、高效的信息交换方式&#xff0c;具有诸多优势。而通过融入二维彩虹技术&#xff0c;电子名片二维码不仅实现了信息的即时传递&#xff0c;更在视觉上为商务交流增…

MySQL的索引和B+tree结构

目录 0.关于索引的常见面试题 1.什么是索引&#xff1f; 索引的优缺点 2.索引的数据结构&#xff0c;为什么InnoDb引擎使用Btree作为索引的数据结构&#xff1f; 分析怎样的索引才是好的 二插搜索树 红黑树 B-Tree BTree 哈希 为什么 InnoDB 存储引擎选择使用 Btree 索…

vue3创建h5 项目使用rem做响应式的配置

第一步 安装依赖&#xff1a; npm install amfe-flexible -S npm install postcss-px2rem -S第二步 main.ts文件中导入 import "amfe-flexible/index.js";第三步 进行配置&#xff1a; vue3 项目中创建 postcss.cinfig.js文件&#xff0c;这里是基于设计稿是750px…

好用的免费的文章一键生成神器

在当今信息爆炸的时代&#xff0c;创作内容是数字营销、网站运营等领域的核心。为了满足日益增长的内容需求&#xff0c;许多GPT生成的软件应运而生&#xff0c;它们能够帮助用户快速生成各种类型的文章&#xff0c;为创作提供了便利和效率。本文将介绍8款不同的免费文章一键生…

springboot3.x 以上,官方不建议使用spring.factories

springboot2.7.x 以上,官方不建议使用spring.factories 最近公司项目升级.需要将springcloud/springboot版本升级到2.7.x以上,再升级的过程中遇到了太多的问题.总结在了如下文章中: springboot艰难版本升级之路!! springboot 2.3.x版本升级到2.7.x版本 这篇文章就重点是梳理一…

力扣180 连续出现的数字

如何有效地识别在数据库中至少连续出现三次的数字&#xff1f; 目录 题目描述 解题思路 完整代码 进一步探索 题目描述 表&#xff1a;Logs ---------------------- | Column Name | Type | ---------------------- | id | int | | num | varch…