HarmonyOS ArkWeb 系列之文本选中菜单定制:editMenuOptions 深度解析
文章目录和 onContextMenuShow 有什么区别核心概念TextMenuItem 和 TextMenuItemId文本菜单定制流程完整示例代码textRange 是什么系统内置 TextMenuItemId 一览几个注意点和 editMenuOptions 对比bindSelectionMenu写在最后选中网页里的文字上面弹出一排小按钮复制、剪切、粘贴……——这排按钮叫文本选中菜单。editMenuOptions让你完全控制这里出现什么。和 onContextMenuShow 有什么区别别搞混onContextMenuShow长按触发适合图片、链接的右键菜单editMenuOptions选中文字后弹出的那一排操作按钮两个是不同场景API 也完全不同。核心概念TextMenuItem 和 TextMenuItemId大白话解释TextMenuItem就是菜单里的一个按钮有三个属性content显示的文字或图标资源id这个按钮的唯一标识用来区分是哪个按钮被点了icon可选按钮旁边的小图标TextMenuItemId是系统内置的 ID 枚举用TextMenuItemId.CUT、TextMenuItemId.COPY这样的方式引用系统默认按钮。自定义按钮用TextMenuItemId.of(你的自定义ID)创建。文本菜单定制流程完整示例代码import{webview}fromkit.ArkWeb;EntryComponentstruct WebTextMenuDemo{controller:webview.WebviewControllernewwebview.WebviewController();// onCreateMenu决定菜单里放哪些按钮// 参数 menuItems 是系统默认的全部菜单项数组onCreateMenu(menuItems:ArrayTextMenuItem):ArrayTextMenuItem{// 第一步从系统菜单里只保留我们想要的letitemsmenuItems.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. 自定义项点击后true和false的区别对于自定义 ID 的按钮true表示点击后不关闭菜单适合多步操作false表示点击后菜单自动关闭。3. 系统 ID 点击后true和false的区别对于系统默认 IDCUT/COPY等true表示拦截系统行为你自己处理false表示让系统执行正常复制粘贴。和editMenuOptions对比bindSelectionMenu特性editMenuOptionsbindSelectionMenu适用对象Web 内文字选中菜单Web 内链接/图片长按菜单菜单样式跟随系统文字选中条完全自定义 Popup/Sheet支持预览不支持支持PREVIEW_MENU触发方式选中文字时自动长按指定元素类型写在最后editMenuOptions是目前定制文字选中菜单最干净的方式不需要拦截手势也不需要注入 JS。如果你的应用需要选中文字后一键翻译/搜索/分享这个 API 正好对味。