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

HarmonyOS ArkWeb 系列之文本选中菜单定制:editMenuOptions 深度解析

文章目录

      • 和 onContextMenuShow 有什么区别?
      • 核心概念:TextMenuItem 和 TextMenuItemId
      • 文本菜单定制流程
      • 完整示例代码
      • `textRange` 是什么
      • 系统内置 TextMenuItemId 一览
      • 几个注意点
      • 和 `editMenuOptions` 对比:bindSelectionMenu
      • 写在最后

选中网页里的文字,上面弹出一排小按钮(复制、剪切、粘贴……)——这排按钮叫"文本选中菜单"。editMenuOptions让你完全控制这里出现什么。

和 onContextMenuShow 有什么区别?

别搞混:

  • onContextMenuShow:长按触发,适合图片、链接的右键菜单
  • editMenuOptions:选中文字后弹出的那一排操作按钮

两个是不同场景,API 也完全不同。

核心概念:TextMenuItem 和 TextMenuItemId

大白话解释:

TextMenuItem就是菜单里的一个按钮,有三个属性:

  • content:显示的文字或图标资源
  • id:这个按钮的唯一标识,用来区分是哪个按钮被点了
  • icon(可选):按钮旁边的小图标

TextMenuItemId是系统内置的 ID 枚举,用TextMenuItemId.CUTTextMenuItemId.COPY这样的方式引用系统默认按钮。自定义按钮用TextMenuItemId.of('你的自定义ID')创建。

文本菜单定制流程

完整示例代码

import{webview}from'@kit.ArkWeb';@Entry@Componentstruct WebTextMenuDemo{controller:webview.WebviewController=newwebview.WebviewController();// onCreateMenu:决定菜单里放哪些按钮// 参数 menuItems 是系统默认的全部菜单项数组onCreateMenu(menuItems:Array<TextMenuItem>):Array<TextMenuItem>{// 第一步:从系统菜单里只保留我们想要的letitems=menuItems.filter((menuItem)=>{return(menuItem.id.equals(TextMenuItemId.CUT)||menuItem.id.equals(TextMenuItemId.COPY)||menuItem.id.equals(TextMenuItemId.PASTE));});// 第二步:添加自定义菜单项letshareItem:TextMenuItem={content:'分享',id:TextMenuItemId.of('action_share'),icon:$r('app.media.share_icon')// 替换为实际图标资源};lettranslateItem:TextMenuItem={content:'翻译',id:TextMenuItemId.of('action_translate'),icon:$r('app.media.translate_icon')};// 在末尾追加自定义项items.push(shareItem);items.push(translateItem);returnitems;}// onMenuItemClick:某个菜单项被点击时的回调// 返回 true = 拦截(系统默认行为不执行)// 返回 false = 不拦截(系统默认行为照常执行)onMenuItemClick(menuItem:TextMenuItem,textRange:TextRange):boolean{if(menuItem.id.equals(TextMenuItemId.CUT)){// 剪切:先做自己的逻辑,再拦截系统行为console.info('用户剪切了文字,范围:',textRange.start,'-',textRange.end);returnfalse;// false = 系统剪切照常执行}if(menuItem.id.equals(TextMenuItemId.COPY)){console.info('用户复制了文字');returnfalse;// 不拦截,让系统正常复制}if(menuItem.id.equals(TextMenuItemId.of('action_share'))){// 自定义分享逻辑console.info('用户点了分享');// ... 调用分享面板returntrue;// true = 菜单保持不关闭(适合需要二级操作的情况)}if(menuItem.id.equals(TextMenuItemId.of('action_translate'))){console.info('用户点了翻译');// ... 调用翻译服务returntrue;}returnfalse;// 默认不拦截}// 把两个回调封装成 EditMenuOptions 对象@StateeditMenuOptions:EditMenuOptions={onCreateMenu:this.onCreateMenu,onMenuItemClick:this.onMenuItemClick};build(){Column(){Web({src:$rawfile('index.html'),controller:this.controller}).editMenuOptions(this.editMenuOptions)// 挂载自定义菜单配置.width('100%').height('100%')}}}

textRange是什么

onMenuItemClick的第二个参数textRange包含用户选中的文字范围:

interfaceTextRange{start?:number;// 选中起始位置(字符索引)end?:number;// 选中结束位置(字符索引)}

你可以用这个范围去 JS 层获取对应的选中文本(配合runJavaScript注入脚本)。

系统内置 TextMenuItemId 一览

ID说明
TextMenuItemId.CUT剪切
TextMenuItemId.COPY复制
TextMenuItemId.PASTE粘贴
TextMenuItemId.SELECT_ALL全选
TextMenuItemId.SHARE分享
TextMenuItemId.TRANSLATE翻译(部分系统支持)
TextMenuItemId.SEARCH搜索

几个注意点

1.onCreateMenu里修改数组顺序就是修改显示顺序

unshift往前插、用push往后加,菜单按你返回的数组顺序排列。

2. 自定义项点击后truefalse的区别

对于自定义 ID 的按钮,true表示点击后不关闭菜单(适合多步操作),false表示点击后菜单自动关闭

3. 系统 ID 点击后truefalse的区别

对于系统默认 ID(CUT/COPY等),true表示拦截系统行为(你自己处理),false表示让系统执行(正常复制粘贴)。

editMenuOptions对比:bindSelectionMenu

特性editMenuOptionsbindSelectionMenu
适用对象Web 内文字选中菜单Web 内链接/图片长按菜单
菜单样式跟随系统文字选中条完全自定义 Popup/Sheet
支持预览不支持支持(PREVIEW_MENU
触发方式选中文字时自动长按指定元素类型

写在最后

editMenuOptions是目前定制文字选中菜单最干净的方式,不需要拦截手势也不需要注入 JS。如果你的应用需要"选中文字后一键翻译/搜索/分享",这个 API 正好对味。

http://www.jsqmd.com/news/825694/

相关文章:

  • 基于MLX框架在苹果芯片Mac本地部署轻量级聊天机器人实践
  • Spring AI MCP案例
  • 船用多AGV路径规划与应用【附程序】
  • 基于STM32F103C8T与FreeJoy打造高性价比模拟飞行控制面板
  • AI写论文不用愁!这4款AI论文写作工具,让期刊论文创作更简单!
  • AI——Dify常见报错与排查
  • 深度解析EASY-HWID-SPOOFER:5大内核级硬件伪装技术实现原理
  • 面向城市计算的时空数据预测与异常检测,城市脉动:用时空数据预测与异常检测解读城市“心跳”
  • 告别低效 HPA:深度解析 Kthena Autoscaler 如何重塑大模型服务弹性
  • 【人类学研究革命性工具】:NotebookLM如何72小时内重构田野笔记分析范式?
  • 从peg/rampart看现代API网关的配置即代码与DSL驱动架构
  • Webasyst框架MCP架构实践:解耦视图逻辑与提升代码可维护性
  • 2026年5月,寻找优质奶酪棒包装机?博川机械以精密制造与一站式服务赢得市场信赖 - 2026年企业推荐榜
  • 2026年5月更新:吕梁实木家居定制市场深度解析与实力厂商推荐 - 2026年企业推荐榜
  • 在VirtualBox虚拟机中安装配置OPENSTEP 4.2:重温NeXTSTEP技术遗产
  • 【WinForm UI控件系列】scratchCode 刮刮乐、识别码、防伪码、验证码控件
  • 医疗电子精密电阻漂移测量与Agilent DMM解决方案
  • “驾驭工程”下一跳?JiuwenClaw AgentTeam开启“协同工程”全新范式
  • Driver Store Explorer终极指南:三步搞定Windows驱动存储清理,轻松释放数GB磁盘空间
  • 告别I2C卡顿!手把手教你用I3C总线驱动传感器(附Arduino ESP32实战代码)
  • Cadence SPB 17.4 + AutoCAD 2022 协同工作流:从机械图纸到PCB板框的无缝转换
  • J Adv Res(IF=13)南方医科大学南方医院等团队:基于多模态渐进融合 Transformer 的肝细胞癌患者免疫治疗反应预测模型
  • Rust高性能跨平台小说下载器:Tomato-Novel-Downloader架构深度解析与技术实现
  • 2026年new消防水带厂家选型指南:鸿安消防如何以综合实力领跑市场 - 2026年企业推荐榜
  • 详解 OpenClaw 小龙虾核心功能与 Windows 部署方法
  • 眼动追踪硬件优化:3D合成数据与NeRF技术应用
  • Roo-Code:基于上下文感知的智能代码生成与增强工具实践
  • 别再只会点灯了!用STM32F103C8T6做个桌面小摆件,串口屏显示天气和名言(附完整工程)
  • ARM活动监控寄存器AMPIDR2详解与应用
  • Tauri自定义窗口踩坑实录:我的拖拽区域为啥不灵?阴影库怎么装?