Android 14新功能HighLights快速实现文本高亮

 更新时间:2023年03月28日 15:38:54   作者:TechMerger  
这篇文章主要为大家介绍了Android 14新功能HighLights快速实现文本高亮示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

日常开发中可能会遇到给 TextView 的全部或部分文本增加高亮效果的需求,以前可能是通过 Spannable 或者 Html 标签实现。

升级 Android 14 后就不用这么迂回了,因其首次引入直接设置高亮的 API:HighLights。需要留意的是 HighLights API 和 Android 1.0 即加入的 textColorHighlight API 不同:

  • 14 的新 API 就是文本在 normal 状态下的高亮,之前这个是为了设置选中时文本高亮,
  • 14 的新 API 只提供了 get/set 方法,没有提供与之匹配的 attribute。而之前的 API还提供了 android:textColorHighlight attribute 配置

下面我们就来一探这个新 API 的玩法和 textColorHighlight API 的区别。

目录前瞻:

  • 设置高亮
  • 获取高亮
  • 动态更新高亮
  • 与选中时效果是否冲突
  • 结语

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 构建一样的高亮效果,然后通过 TextViewsetHighLights() 反映。

 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 的默认浅灰色。

5. 结语

可以看到新功能 HighLights 可以使得高亮的处理变得简单、易用,大家可以在 14 上采用该 API,当高版本普及后,低版本上的自定义高亮逻辑就可以舍弃了。

至于其原理,因为 Android 14 尚处于预览版阶段、源码没有公开,无法获悉实现。但估计是 TextViewdraw 阶段会获取设置的 HighLights 包含的 size 以及对应的 PaintRanges,得以清晰地掌握各高亮的颜色和对应的范围,然后直接调用 CanvasdrawText(text, start, end, x, y, paint) 去完成绘制。

可以说 HighLights 这种 API 既方便了开发者的使用:从设置高亮到获取高亮到动态更新高亮,其清晰的逻辑一定程度上也可以简化 SDK 的实现。

事实上 Android 14 还针对 TextView 做了其他新功能的支持,比如设置文内搜索结果的文本高亮、索引,后续一并进行解读:

  • setSearchResultHighlightColor(int color):设置所有匹配到搜索关键字的文本颜色
  • setSearchResultHighlights(int... ranges):设置所有匹配到搜索关键字的文本高亮 HighLights 的范围
  • setFocusedSearchResultHighlightColor(int color):设置当前聚焦到的匹配关键字的文本颜色
  • setFocusedSearchResultIndex(int index):设置当前聚焦到的匹配关键字的索引

参考

以上就是Android 14新功能HighLights快速实现文本高亮的详细内容,更多关于Android HighLights文本高亮的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

相关文章

  • Flutter简洁实用的图片编辑器的实现

    Flutter简洁实用的图片编辑器的实现

    本文主要介绍了Flutter简洁实用的图片编辑器的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 基于flutter sound插件实现录音与播放功能

    基于flutter sound插件实现录音与播放功能

    这篇文章主要介绍了基于flutter sound插件实现录音与播放功能,介绍了如何录音,如何播放本地和远程音频文件,以及如何实现动画,在录制完音频文件后如何上传,这些都是我们平常使用这个功能会遇到的问题。在使用的过程中遇到的问题也有列出,需要的朋友可以参考下
    2022-05-05
  • Android PhoneWindowManager监听屏幕右侧向左滑动实现返回功能

    Android PhoneWindowManager监听屏幕右侧向左滑动实现返回功能

    这篇文章主要介绍了Android PhoneWindowManager监听屏幕右侧向左滑动实现返回功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Android浅析viewBinding和DataBinding

    Android浅析viewBinding和DataBinding

    这篇文章主要介绍了Android浅析viewBinding和DataBinding,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • 详解android 视频图片混合轮播实现

    详解android 视频图片混合轮播实现

    这篇文章主要介绍了android 视频图片混合轮播实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Flutter组件实现进度指示器

    Flutter组件实现进度指示器

    这篇文章主要为大家详细介绍了Flutter组件实现进度指示器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 6步轻松实现两个listView联动效果

    6步轻松实现两个listView联动效果

    这篇文章主要为大家详细介绍了教大家通过6步轻松实现两个listView联动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • Android自定义View实现天气预报折线图

    Android自定义View实现天气预报折线图

    这篇文章主要为大家详细介绍了Android自定义View实现天气预报折线图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • Jetpack Compose实现动画效果的方法详解

    Jetpack Compose实现动画效果的方法详解

    compose为支持动画提供了大量的 api,通过这些 api 我们可以轻松实现动画效果。本文将为大家介绍利用compose实现的多种动画效果的示例代码,需要的可以参考一下
    2022-02-02
  • Android Scroller的使用方法

    Android Scroller的使用方法

    这篇文章主要为大家详细介绍了Android Scroller的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05

最新评论