查看: 126|回复: 1

HarmonyOS NEXT 6.1 TextController动态高亮选区实战解析

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在构建交互式移动应用时,文本内容的动态选择与高亮是提升用户体验的关键。过去,开发者只能依赖用户长按或双击来触发系统默认的文本选区,无法通过代码主动控制。HarmonyOS NEXT 6.1(API 23)对 ArkUI 的 Text 控制器进行了重要升级,新增了 setTextSelection() 接口,允许开发者动态指定文本索引区间并触发原生高亮框选,彻底打破了应用层与底层选区状态机之间的壁垒。

一、Kit 能力与原理
在 ArkUI 的文本渲染管线中,Text 组件开启 copyOption 后,底层会自动激活选区高亮渲染层与剪贴板通道。API 23 之前,这个高亮层被封闭在系统手势状态机内部,应用层无法干预;新接口 setTextSelection() 则允许指令越过手势拦截层,直接将起始索引和结束索引注入底层选区状态机。随后,ArkUI 的文本测量层(Paragraph)计算字符的物理坐标,在不触发重排的前提下在指定区域局部叠加绘制半透明蓝色高亮色块,并可根据配置弹出原生复制、全选等功能菜单。

二、API 定义与约束
接口原型如下:
  1. setTextSelection(
  2.   selectionStart: number | undefined,
  3.   selectionEnd: number | undefined,
  4.   options?: SelectionOptions
  5. ): void;
复制代码
关键约束包括:
- selectionStart 和 selectionEnd 取值范围 [0, +∞),若为负数或 undefined 则按 0 处理。
- 必须将 Text 组件的 copyOption 设置为非 CopyOptions.None 的值(如 CopyOptions.InApp),否则调用被静默拦截。
- 当 textOverflow 属性配置为 TextOverflow.MARQUEE(跑马灯模式)时,接口不生效。
- 若 selectionStart >= selectionEnd,视为无效选区。
- 选区最大范围为 [0, textSize],超出 textSize 的索引会被安全截断。
- 若选区索引处于不可见截断区域(由于滚动或尺寸限制),高亮不会生效。
- PC/2in1 设备上即使设置 MenuPolicy.SHOW,也不会主动弹出二级菜单。
- Emoji 字符被截断时会被作为一个完整单元选中。
- 系统能力:SystemCapability.ArkUI.ArkUI.Full,API 23 起支持元服务调用,覆盖 Phone、PC/2in1、Tablet、TV、Wearable。

三、实战开发步骤
以下是一个完整的示例,展示如何在应用中实现动态选区高亮。首先,在 Text 组件上绑定 TextController 并设置 copyOption:
  1. private textController: TextController = new TextController();
  2. private testTextValue: string = 'HarmonyOS NEXT 极客排版与动态选区高亮技术(API 23)';
  3. // 在 build() 中
  4. Text(this.testTextValue, { controller: this.textController })
  5.   .copyOption(CopyOptions.InApp) // 必须配置,否则无效
  6.   .fontSize(16)
  7.   .fontColor('#FFFFFF')
  8.   .lineHeight(24)
  9.   .width('100%')
  10.   .padding(12)
  11.   .backgroundColor('#111111')
  12.   .borderRadius(8);
复制代码
然后,通过按钮触发动态选择:
  1. Button('触发 setTextSelection')
  2.   .onClick(() => {
  3.     try {
  4.       this.textController.setTextSelection(
  5.         this.selectionStartInput,
  6.         this.selectionEndInput,
  7.         { menuPolicy: MenuPolicy.SHOW }  // 显示系统菜单
  8.       );
  9.       // 更新日志
  10.     } catch (err) {
  11.       // 异常处理
  12.     }
  13.   });
复制代码
清除选区时,传入相等或无效的索引即可:
  1. this.textController.setTextSelection(0, 0); // 起始>=结束,不选中
复制代码
注意:输入框应绑定状态变量并转为整数,避免非法输入。完整示例中建议添加文本总字符数提示和操作日志输出,便于调试。

四、运行效果与性能
在实测中,输入起始索引 0、结束索引 10,点击触发后,“HarmonyOS ” 瞬间被蓝色半透明高亮覆盖,同时弹出系统原生复制、搜索等菜单,与用户长按效果一致。即使将索引设为超出文本长度(如 999),系统自动截断到末尾,无任何异常。在高频快速点击(30Hz+)时,CPU 占用率极低,无卡顿重排,性能表现出色。

五、避坑指南
1. CopyOptions.None 导致静默失效:忘记设置 copyOption 或误设为 None,setTextSelection() 不会报错但不产生任何效果。务必显式设置为 CopyOptions.InApp 或 CopyOptions.LocalDevice。
2. 不可见截断区域导致“选择哑弹”:如果 Text 组件限制了高度/宽度且使用了 textOverflow 截断,索引指向被截断的不可见字符时,高亮无法生效。解决方案是结合滚动视图(如 Scroll),或者关闭截断(不设 textOverflow),确保所有字符在排版树中可见。

六、总结
setTextSelection() 接口使开发者能够以代码方式精确控制文本选区高亮,并与系统原生菜单联动,为 AI 划词、动态标注、语音阅读同步高亮等场景提供了原生级性能支持。开发者应充分利用 API 23 的这一能力,重构传统通过拆分 Text 组件实现高亮的做法,获得更流畅、更贴近系统体验的交互效果。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: HarmonyOS NEXT 6.1 TextController动态高亮选区实战解析

感谢鸿蒙专家的深度解析!这篇实战指南非常清晰,从原理到代码细节都讲得很透彻,尤其是避坑部分——把`copyOption`遗漏和不可见截断区这两个最容易踩的坑点出来,对实际开发帮助很大。 一直很想在文本标注场景里用代码控制选区,之前只能靠拆Text组件模拟,性能确实有瓶颈。`setTextSelection()`直接操作底层选区状态机,加上不触发重排的局部绘制,这个设计思路确实漂亮。想请教一个问题:如果Text组件放在`Scroll`里且内容滚动,调用`setTextSelection()`选中一个当前不可见的索引区间时,组件会自动滚动到对应位置吗?还是需要开发者手动调滚动?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-4 20:18 , Processed in 0.026912 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部