这篇文章主要介绍了Android14新功能HighLights怎么快速实现文本高亮的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android14新功能HighLights怎么快速实现文本高亮文章都会有所收获,下面我们一起来看看吧。
日常开发中可能会遇到给 TextView 的全部或部分文本增加高亮效果的需求,以前可能是通过
Spannable或者
Html标签实现。
升级 Android 14 后就不用这么迂回了,因其首次引入直接设置高亮的 API:
HighLights。需要留意的是 HighLights API 和 Android 1.0 即加入的
textColorHighlightAPI 不同:
14 的新 API 就是文本在 normal 状态下的高亮,之前这个是为了设置选中时文本高亮,
14 的新 API 只提供了 get/set 方法,没有提供与之匹配的 attribute。而之前的 API还提供了 android:
textColorHighlightattribute 配置
1. 设置高亮
HighLights采用的是熟知的建造者模式,即首先需要构建不同参数的
Builder实例,针对参数也提供了两种设置方式:
一次指定单组高亮配置:addRange(Paint paint, int start, int end),如果多组需要设置同样高亮颜色的话,那要调用多次
一次指定多组高亮配置:addRange(Paint paint, int... ranges),如果多组需要设置同样高亮颜色的话,只要调用一次即可
既然是多组范围那么 int 参数必须是偶数数目的,即成对出现,反之会发生如下的 Exception:
java.lang.IllegalArgumentException: Flatten ranges must have even numbered elements
可以说上述两个 API 的参数都是成对出现,对于高亮的响应范围的话:前者是包含 inclusive 在内的,后者是不包含 exclusive 在内的,需要注意。
我们通过代码实例演示通过上述两个 Builder API 构建一样的高亮效果,然后通过
TextView的
setHighLights()反映。
class MainActivity : AppCompatActivity() { companion object { const val TEXT = "val builder = Highlights.Builder()" } override fun onCreate(savedInstanceState: Bundle?) { ... val yellowPaint = Paint().apply { color = Color.YELLOW } val greenPaint = Paint().apply { color = Color.GREEN } with(binding.textview1) { text = TEXT val builder = Highlights.Builder() .addRange(yellowPaint, 0, 3) .addRange(greenPaint, 14, 24) .addRange(greenPaint, 25, 32) highlights = builder.build() } with(binding.textview2) { text = TEXT val builder = Highlights.Builder() .addRanges(yellowPaint, 0, 3) .addRanges(greenPaint, 14, 24, 25, 32) highlights = builder.build() } } }
可以看到不同的 Builder 参数设置方式可以对 val 设置黄色高亮,Highlights 和 Builder 设置绿色高亮。
2. 获取高亮
设置到 TextView 对象的 HighLights 实例还可以通过
getHighlights()获取,并通过如下的 API 获取高亮的细节:
首先通过
getSize()获取设置高亮的数量
其次从 0 开始遍历下标
通过
getPaint(int index)获取高亮的
Paint对象
以及通过
getRanges(int index)获取对应的 Paint 范围
Ranges(也是一个数组,需要遍历打印具体的起始位置)
class MainActivity : AppCompatActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { ... binding.textview1.highlights?.run { Log.d("HighLights", "textview1 usedHighLights' size:$size") for (i in 0 until size) { Log.d("HighLights", "usedHighLights'" + " paint:${getPaint(i).color.toColorString()}") val range = getRanges(i) for (j in range.indices) { Log.d("HighLights", "ranges:${range[j]}") } } } binding.textview2.highlights?.run { Log.d("HighLights", "textview2 usedHighLights' size:$size") for (i in 0 until size) { Log.d("HighLights", "usedHighLights'" + " paint:${getPaint(i).color.toColorString()}") val range = getRanges(i) for (j in range.indices) { Log.d("HighLights", "ranges:${range[j]}") } } } } }
如下的 log 可以看到打印出来的 Paint 颜色、范围 Ranges 和设置的参数是一一对应的。
03-23 23:08:27.196 7182 7182 D HighLights: textview1 usedHighLights' size:3
03-23 23:08:27.196 7182 7182 D HighLights: usedHighLights' paint:YELLOW
03-23 23:08:27.196 7182 7182 D HighLights: ranges:0
03-23 23:08:27.196 7182 7182 D HighLights: ranges:3
03-23 23:08:27.196 7182 7182 D HighLights: usedHighLights' paint:GREEN
03-23 23:08:27.196 7182 7182 D HighLights: ranges:14
03-23 23:08:27.196 7182 7182 D HighLights: ranges:24
03-23 23:08:27.196 7182 7182 D HighLights: usedHighLights' paint:GREEN
03-23 23:08:27.196 7182 7182 D HighLights: ranges:25
03-23 23:08:27.196 7182 7182 D HighLights: ranges:32
03-23 23:08:27.196 7182 7182 D HighLights: textview2 usedHighLights' size:2
03-23 23:08:27.196 7182 7182 D HighLights: usedHighLights' paint:YELLOW
03-23 23:08:27.196 7182 7182 D HighLights: ranges:0
03-23 23:08:27.196 7182 7182 D HighLights: ranges:3
03-23 23:08:27.196 7182 7182 D HighLights: usedHighLights' paint:GREEN
03-23 23:08:27.196 7182 7182 D HighLights: ranges:14
03-23 23:08:27.196 7182 7182 D HighLights: ranges:24
03-23 23:08:27.196 7182 7182 D HighLights: ranges:25
03-23 23:08:27.196 7182 7182 D HighLights: ranges:32
3. 动态更新高亮
既然我们可以获取已经设置的 HighLights,那么更新其属性,能否动态更新高亮效果呢?
首先在 TextView 下添加动态更新 HighLights 的 Button
然后点击该 Button 之后将 textView1 的 Paint 颜色从 GREEN 改为 BLUE,并将其中 “Highlights” 的文本范围增大:头尾各扩展一个或多个下标
class MainActivity : AppCompatActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { ... binding.changeHighlights.setOnClickListener { Log.d("HighLights", "changeHighlights tapped & change highlights") textView1Highlights?.apply { // Change color getPaint(1).color = Color.BLUE // Change ranges getRanges(1)[0] -= 3 getRanges(1)[1] += 1 for (i in 0 until size) { Log.d("HighLights", "textView1Highlights'" + " paint:${getPaint(i).color.toColorString()}") val range = getRanges(i) for (j in range.indices) { Log.d("HighLights", "ranges:${range[j]}") } } } binding.textview1.invalidate() } } }
点击 Button 之后,颜色确实变成了蓝色,但是高亮范围却没有变化。
我们打印的更新后 HighLights 的参数 log:可以看到,无论是颜色(GREEN -> BLUE)还是范围(14 -> 11,24 -> 25)确实都已经更改了。
可为什么唯独 Ranges 没有刷新?有可能是 14 预览版阶段的 Bug。
03-25 10:47:29.276 5344 5344 D HighLights: changeHighlights tapped & change highlights
03-25 10:47:29.276 5344 5344 D HighLights: textview1 textView1Highlights' size:3
03-25 10:47:29.276 5344 5344 D HighLights: textView1Highlights' paint:YELLOW
03-25 10:47:29.276 5344 5344 D HighLights: ranges:0
03-25 10:47:29.276 5344 5344 D HighLights: ranges:3
03-25 10:47:29.277 5344 5344 D HighLights: textView1Highlights' paint:BLUE
03-25 10:47:29.277 5344 5344 D HighLights: ranges:11
03-25 10:47:29.277 5344 5344 D HighLights: ranges:25
03-25 10:47:29.277 5344 5344 D HighLights: textView1Highlights' paint:BLUE
03-25 10:47:29.277 5344 5344 D HighLights: ranges:25
03-25 10:47:29.277 5344 5344 D HighLights: ranges:32
4. 与选中时效果是否冲突
我们给上述其中一个 TextView 添加选中高亮颜色的配置即
textColorHighlight,该颜色与上述 HighLights 颜色不同,以清晰地判断两种高亮是否会发生冲突。
注意需要将
textIsSelectable设置为 true,这样 TextView 才可以被长按选中。
<androidx.constraintlayout.widget.ConstraintLayout ... > <TextView android:id="@+id/textview1" ... android:textColorHighlight="@color/purple_200" android:textIsSelectable="true" ... /> < ... > </androidx.constraintlayout.widget.ConstraintLayout>
我们在该 TextView 上长按看一下效果:
可以看到水滴选中的范围内会变成我们设置的 textColorHighlight 紫色高亮,未选中的部分会按照 HighLights 配置的那样展示黄色和绿色以及没有设置 HighLights 的默认浅灰色。