Android 14 新功能之 Highlights: 快速实现文本高亮 | 开发者说·DTalk
The following article is from TechMerger Author 小虾米君
日常开发中可能会遇到给 TextView 的全部或部分文本增加高亮效果的需求,以前可能是通过 Spannable 或者 Html 标签实现。
升级 Android 14 后就不用这么迂回了,因其首次引入直接设置高亮的 API: Highlights。需要留意的是 Highlights API 和 Android 1.0 即加入的 textColorHighlight API 不同:
Android 14 的新 API 就是文本在 normal 状态下的高亮,之前这个是为了设置选中时文本高亮 Android 14 的新 API 只提供了 get/set 方法,没有提供与之匹配的 attribute。而之前的 API 还提供了 android: textColorHighlight attribute 配置
下面我们就来一探这个新 API 的玩法和 textColorHighlight API 的区别。
设置高亮
一次指定单组高亮配置: addRange(Paint paint, int start, int end),如果多组需要设置同样高亮颜色的话,那要调用多次
一次指定多组高亮配置: addRange(Paint paint, int... ranges),如果多组需要设置同样高亮颜色的话,只要调用一次即可
java.lang.IllegalArgumentException: Flatten ranges must have even numbered elements
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()
}
}
}
获取高亮
首先通过 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]}")
}
}
}
}
}
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
动态更新高亮
首先在 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()
}
}
}
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
与选中时效果是否冲突
<androidx.constraintlayout.widget.ConstraintLayout ... >
<TextView
android:id="@+id/textview1"
...
android:textColorHighlight="@color/purple_200"
android:textIsSelectable="true"
... />
< ... >
</androidx.constraintlayout.widget.ConstraintLayout>
结语
setSearchResultHighlightColor(int color): 设置所有匹配到搜索关键字的文本颜色
setSearchResultHighlights(int... ranges): 设置所有匹配到搜索关键字的文本高亮 Highlights 的范围 setFocusedSearchResultHighlightColor(int color): 设置当前聚焦到的匹配关键字的文本颜色 setFocusedSearchResultIndex(int index): 设置当前聚焦到的匹配关键字的索引
长按右侧二维码
查看更多开发者精彩分享
"开发者说·DTalk" 面向