文章目录先搞清楚右键菜单是什么流程图右键菜单触发全流程最简实现把系统菜单换成自己的几个容易踩的坑event.param 都能拿到什么result 能执行哪些操作写在最后长按网页里的链接或图片系统弹出一个菜单——这个菜单能不能换成我们自己设计的样式答案是可以。onContextMenuShow就是干这个的。先搞清楚右键菜单是什么在手机上长按网页中的文字、图片、链接会弹出一个操作菜单复制、粘贴、保存图片……。在桌面端就是鼠标右键菜单。ArkWeb 的onContextMenuShow回调在这个时机触发给你两个关键参数event.param当前长按位置的信息坐标、链接地址、图片地址……event.result操作句柄调它的方法可以执行复制/粘贴/关闭菜单等系统行为返回true表示我自己处理系统别弹了返回false表示用系统默认菜单就行。流程图右键菜单触发全流程最简实现把系统菜单换成自己的import{webview}fromkit.ArkWeb;import{pasteboard}fromkit.BasicServicesKit;EntryComponentstruct WebContextMenuDemo{controller:webview.WebviewControllernewwebview.WebviewController();// 保存菜单操作句柄点菜单项时调用privateresult:WebContextMenuResult|undefinedundefined;StatelinkUrl:string;StateshowMenu:booleanfalse;StateoffsetY:number0;uiContext:UIContextthis.getUIContext();// 用 Builder 声明自定义菜单内容BuilderMenuBuilder(){Menu(){MenuItem({content:复制图片}).width(200).height(50).onClick((){this.result?.copyImage();// 调系统复制图片this.showMenufalse;})MenuItem({content:剪切}).width(200).height(50).onClick((){this.result?.cut();this.showMenufalse;})MenuItem({content:复制}).width(200).height(50).onClick((){this.result?.copy();this.showMenufalse;})MenuItem({content:粘贴}).width(200).height(50).onClick((){this.result?.paste();this.showMenufalse;})MenuItem({content:复制链接}).width(200).height(50).onClick((){// 手动写入剪贴板letpasteDatapasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN,this.linkUrl);pasteboard.getSystemPasteboard().setData(pasteData,(error){if(error){return;}});this.showMenufalse;})MenuItem({content:全选}).width(200).height(50).onClick((){this.result?.selectAll();this.showMenufalse;})}.width(150).height(300)}build(){Column(){Web({src:$rawfile(index.html),controller:this.controller}).onContextMenuShow((event){if(event){// 保存句柄和链接地址this.resultevent.result;this.linkUrlevent.param.getLinkUrl();// 根据长按 Y 坐标定位菜单弹出位置this.offsetYMath.max(this.uiContext.px2vp(event.param.y()??0)-0,0);}this.showMenutrue;returntrue;// 关键返回 true 阻止系统菜单}).bindPopup(this.showMenu,{builder:this.MenuBuilder(),enableArrow:false,placement:Placement.LeftTop,offset:{x:0,y:this.offsetY},mask:false,onStateChange:(e){if(!e.isVisible){this.showMenufalse;this.result?.closeContextMenu();// 菜单消失时通知内核关闭}}})}}}几个容易踩的坑坑1忘记调closeContextMenu()菜单消失后如果不调这个Web 内核状态不同步下次再长按可能出问题。一定要在onStateChange里菜单不可见时调一次。坑2event.param.y()返回的是像素值屏幕坐标是 pxArkUI 布局用的是 vp需要用this.getUIContext().px2vp()转换否则菜单位置会乱。坑3result保存时机result必须在onContextMenuShow回调里保存不能用成员变量直接操作因为每次长按都是一个新的result对象。event.param都能拿到什么方法说明x()/y()长按位置坐标pxgetLinkUrl()链接地址getUnfilteredLinkUrl()原始链接未过滤getSourceUrl()图片/媒体资源地址existsImageContents()当前位置是否有图片getPreviewWidth()/getPreviewHeight()图片预览尺寸pxresult能执行哪些操作方法说明copy()复制选中内容cut()剪切选中内容paste()粘贴copyImage()复制图片selectAll()全选closeContextMenu()关闭上下文菜单写在最后onContextMenuShow的设计很灵活你既可以完全替换菜单也可以只监听事件做一些统计、日志记录然后返回false让系统菜单照常弹出。根据实际需求选择就行不必过度封装。
HarmonyOS ArkWeb 系列之 右键菜单完全自定义:onContextMenuShow 用法详解
文章目录先搞清楚右键菜单是什么流程图右键菜单触发全流程最简实现把系统菜单换成自己的几个容易踩的坑event.param 都能拿到什么result 能执行哪些操作写在最后长按网页里的链接或图片系统弹出一个菜单——这个菜单能不能换成我们自己设计的样式答案是可以。onContextMenuShow就是干这个的。先搞清楚右键菜单是什么在手机上长按网页中的文字、图片、链接会弹出一个操作菜单复制、粘贴、保存图片……。在桌面端就是鼠标右键菜单。ArkWeb 的onContextMenuShow回调在这个时机触发给你两个关键参数event.param当前长按位置的信息坐标、链接地址、图片地址……event.result操作句柄调它的方法可以执行复制/粘贴/关闭菜单等系统行为返回true表示我自己处理系统别弹了返回false表示用系统默认菜单就行。流程图右键菜单触发全流程最简实现把系统菜单换成自己的import{webview}fromkit.ArkWeb;import{pasteboard}fromkit.BasicServicesKit;EntryComponentstruct WebContextMenuDemo{controller:webview.WebviewControllernewwebview.WebviewController();// 保存菜单操作句柄点菜单项时调用privateresult:WebContextMenuResult|undefinedundefined;StatelinkUrl:string;StateshowMenu:booleanfalse;StateoffsetY:number0;uiContext:UIContextthis.getUIContext();// 用 Builder 声明自定义菜单内容BuilderMenuBuilder(){Menu(){MenuItem({content:复制图片}).width(200).height(50).onClick((){this.result?.copyImage();// 调系统复制图片this.showMenufalse;})MenuItem({content:剪切}).width(200).height(50).onClick((){this.result?.cut();this.showMenufalse;})MenuItem({content:复制}).width(200).height(50).onClick((){this.result?.copy();this.showMenufalse;})MenuItem({content:粘贴}).width(200).height(50).onClick((){this.result?.paste();this.showMenufalse;})MenuItem({content:复制链接}).width(200).height(50).onClick((){// 手动写入剪贴板letpasteDatapasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN,this.linkUrl);pasteboard.getSystemPasteboard().setData(pasteData,(error){if(error){return;}});this.showMenufalse;})MenuItem({content:全选}).width(200).height(50).onClick((){this.result?.selectAll();this.showMenufalse;})}.width(150).height(300)}build(){Column(){Web({src:$rawfile(index.html),controller:this.controller}).onContextMenuShow((event){if(event){// 保存句柄和链接地址this.resultevent.result;this.linkUrlevent.param.getLinkUrl();// 根据长按 Y 坐标定位菜单弹出位置this.offsetYMath.max(this.uiContext.px2vp(event.param.y()??0)-0,0);}this.showMenutrue;returntrue;// 关键返回 true 阻止系统菜单}).bindPopup(this.showMenu,{builder:this.MenuBuilder(),enableArrow:false,placement:Placement.LeftTop,offset:{x:0,y:this.offsetY},mask:false,onStateChange:(e){if(!e.isVisible){this.showMenufalse;this.result?.closeContextMenu();// 菜单消失时通知内核关闭}}})}}}几个容易踩的坑坑1忘记调closeContextMenu()菜单消失后如果不调这个Web 内核状态不同步下次再长按可能出问题。一定要在onStateChange里菜单不可见时调一次。坑2event.param.y()返回的是像素值屏幕坐标是 pxArkUI 布局用的是 vp需要用this.getUIContext().px2vp()转换否则菜单位置会乱。坑3result保存时机result必须在onContextMenuShow回调里保存不能用成员变量直接操作因为每次长按都是一个新的result对象。event.param都能拿到什么方法说明x()/y()长按位置坐标pxgetLinkUrl()链接地址getUnfilteredLinkUrl()原始链接未过滤getSourceUrl()图片/媒体资源地址existsImageContents()当前位置是否有图片getPreviewWidth()/getPreviewHeight()图片预览尺寸pxresult能执行哪些操作方法说明copy()复制选中内容cut()剪切选中内容paste()粘贴copyImage()复制图片selectAll()全选closeContextMenu()关闭上下文菜单写在最后onContextMenuShow的设计很灵活你既可以完全替换菜单也可以只监听事件做一些统计、日志记录然后返回false让系统菜单照常弹出。根据实际需求选择就行不必过度封装。