当前位置: 首页 > article >正文

Android TextView实现一串文字特定几个字改变颜色

遇到一个需求,让Android端实现给定一个字符串指定下标的几个字颜色与其他字颜色不一致。

主要是用ForegroundColorSpan这个API来传入颜色值,用SpannableString来设置指定索引下标的字的颜色值。

这里通过给定一个输入文字描述框,要求输入指定下标,输入格式类似于1,3,4,6。输入数字,同时用英文逗号隔开,只要点击按钮提交以后,则来改变显示的字体颜色。

布局文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <EditText
        android:id="@+id/edit_num"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入下标(例如 1,3,5)"
        tools:ignore="MissingConstraints">

    </EditText>

    <Button
        android:id="@+id/submit"
        android:text="提交"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.467"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/edit_num"
        app:layout_constraintVertical_bias="0.26"
        tools:ignore="MissingConstraints">

    </Button>

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="HelloWorld"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity如下所示:



import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.widget.Button
import android.widget.EditText
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val indexInput = findViewById<EditText>(R.id.edit_num)
        val textView = findViewById<TextView>(R.id.text_view)
        val buttonSubmit = findViewById<Button>(R.id.submit)

        val originalText = "HelloWorld  测试文字颜色变化"

        // 初始化显示原始文本
        textView.text = originalText

        buttonSubmit.setOnClickListener {
            val s = indexInput.text
            val strArray = s?.toString()
            val indexArray = strArray?.split(",")

            val len = indexArray?.size ?: 20
            val indexNumArray = IntArray(len){0}
            // 创建 SpannableString
            val spannableString = SpannableString(originalText)
            indexArray?.let {
                for (i in indexArray.indices) {
                    indexNumArray[i] = Integer.parseInt(indexArray[i])
                    val idx = indexNumArray[i]

                    // 检查下标是否有效,避免越界错误
                    if (idx in originalText.indices) {
                        // 为每个字符创建一个新的 ForegroundColorSpan
                        val redColorSpan = ForegroundColorSpan(Color.RED)
                        spannableString.setSpan(
                            redColorSpan,
                            idx,
                            idx + 1,
                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                        )
                    }
                }
            }
            textView.text = spannableString
        }
    }
}

其中这里有个需要注意的是:

如果需要多次变更字体颜色,需要把ForegroundColorSpan设置在循环体内。如果把ForegroundColorSpan放在循环体外,则只有最后一个字会生效。错误示例如下:

        val redColorSpan = ForegroundColorSpan(Color.RED)
            indexArray?.let {
                for (i in indexArray.indices) {
                    indexNumArray[i] = Integer.parseInt(indexArray[i])
                    val idx = indexNumArray[i]
                    spannableString.setSpan(redColorSpan, idx, idx + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)  // 第index个字

                }
            }

问题原因:

  • 你在循环中对每个字符的位置都应用了相同的 ForegroundColorSpan(红色),并且每次调用 setSpan 时,该 Span 会替换之前的位置上的 Span,导致只有最后一个字符保持红色。

解决方案:

为了解决这个问题,确保为每个字符应用不同的颜色时不要覆盖先前的 Span。可以通过创建一个新的 ForegroundColorSpan 实例,并在每次 setSpan 时分别应用。

关键更改:

  1. 确保每次 setSpan 使用新的 ForegroundColorSpan 对象
    • 在每次循环中创建一个新的 ForegroundColorSpan 实例,确保不会覆盖先前的颜色设置。
  2. 下标校验
    • setSpan 之前,确保你所提供的下标值是合法的,避免越界问题(idx in 0 until originalText.length)。
  3. IntArray 初始化
    • 使用 IntArray 来存储转换后的下标值,并确保在处理时进行合理的范围检查。

效果:

当用户输入下标(例如 1,3,5),然后点击按钮时,指定下标的字符将正确变为红色,不会再出现只有最后一个字符变色的情况。


http://www.kler.cn/a/349231.html

相关文章:

  • 浅谈Java之MBus通信
  • std::function的概念和使用方法
  • 硬盘文件误删:原因、恢复方案与预防措施
  • “探索端智能,加速大模型应用” 火山引擎边缘智能x扣子技术沙龙圆满落幕!
  • 机器人研究不同模态之间的融合方法
  • OpenAI Canvas:提升编程与写作效率的全新工作界面
  • Shiro 认证(Authentication)
  • 实战篇:(二)React 创建项目并连接 MySQL 后台的实战教程
  • STM32的SPI技术介绍
  • kubernetes中的微服务
  • 开启您的财富增值之路
  • B3622 枚举子集
  • 如何查看GB28181流媒体平台LiveGBS中对GB28181实时视频数据统计的负载信息
  • js 去重的方法
  • 一篇文章带你快速了解linux中关于信号的核心内容
  • 水凝胶微型机器人,材料多样性能优
  • Multiprocessing出错没有提示was skipped without notice in python
  • 有两个水桶,容量分别为5升和3升,请问如何使用这两个桶得到4升的水?
  • vue3ElementPlu表格合并多行
  • 【基础篇】哨兵集群:哨兵挂了,主从库还能切换吗?