HarmonyOS鸿蒙Next中AI识图文字提取,在选中文字后,如何屏蔽系统自带的“复制”,“全选”,“翻译”等菜单选项

HarmonyOS鸿蒙Next中AI识图文字提取,在选中文字后,如何屏蔽系统自带的“复制”,“全选”,“翻译”等菜单选项 如题所示,在开发阶段,使用了鸿蒙的AI识图文字提取,在选中文字后,希望可以自定义菜单,而不是放在四个点点选后才能显示出来。

因为这里有一些版权问题,不希望在APP中就可以复制图片中的文字,同时又希望给用户一些其他选项的帮助。具体来说:就是屏蔽系统自带的“复制”,“全选”,“翻译”等菜单选项,由开发者添加自己想用的菜单按钮

this.aiController.setCustomTextMenuItems([
  {
    value: '播放',
    action: (param: string | visionImageAnalyzer.Subject[]) => {
      if (typeof param === 'string') {
       
      }
    }
  },
  {
    value: '搜题',
    action: (param: string | visionImageAnalyzer.Subject[]) => {

    }
  }
])

cke_624.png


更多关于HarmonyOS鸿蒙Next中AI识图文字提取,在选中文字后,如何屏蔽系统自带的“复制”,“全选”,“翻译”等菜单选项的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

如果选区来自 AI 识图在 Image 上生成的识别浮层,而不是你自己渲染的 Text/RichEditor,那 EditMenuOptions、TextMenuController、selectionMenuHidden 这类 Text/RichEditor 侧能力大概率覆盖不到它。它们管的是文本组件的选择菜单,不一定能接管 AI controller 内部的系统菜单。

这种情况下要看 aiController 是否提供“替换/禁用系统项”的明确接口;如果没有,比较稳的方案是关闭/避开内置可选择浮层,把 OCR 结果拿出来后自己渲染一层文本或区域标注,再在自有组件上控制菜单。这样才能同时做到版权控制和自定义操作入口。

更多关于HarmonyOS鸿蒙Next中AI识图文字提取,在选中文字后,如何屏蔽系统自带的“复制”,“全选”,“翻译”等菜单选项的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


你这个补充是对的:如果控件本体是 Image,菜单来自 AI 识图内部选区,而不是 Text/Editor/TextArea,那么 Text 系列的 selectionMenuHidden、EditMenuOptions、TextMenuController 都不在同一条能力链路上,套这些方案基本不会生效。

所以目前可以把边界说清楚:setCustomTextMenuItems 只能增加自定义项,不等于隐藏系统项;如果 aiController 没有暴露禁用“复制/全选/翻译”的接口,就不能从 Image 外层强行改这个系统菜单。要做版权控制,更稳的是不要使用内置可复制选区,改成拿 OCR 结果后自绘选区/按钮,或者只展示你允许的识别结果交互。

方案一:利用隐藏selectionMenuHidden属性系统文本选择菜单,示例代码如下:

@Entry
@Component
struct ProhibitLongPressPopupMenuOne {
  @State message: string = '';

  build() {
    Column() {
      Text(`输入的内容: ${this.message}`).margin({ top: 100, bottom: 30 });
      TextInput({ placeholder: '请输入内容' })
        .margin({ left: 16, right: 16 })
        .borderRadius(10)
        .onChange((value: string) => {
          this.message = value;
        })
        .selectionMenuHidden(true);
    }
    .height('100%')
    .width('100%');
  }
}

方案二:拦截整个默认菜单并使用自定义bindContextMenu替代。

  1. 令数组返回空请求,从而拦截整个editMenu。
  2. 定义bindContextMenu,实际内容和功能需要自定义。
  3. editMenuOptions自定义菜单扩展项,允许用户设置扩展项的文本内容、图标、回调方法。

示例代码如下:

@Entry
@Component
struct ProhibitLongPressPopupMenuTwo {
  @State start: number = 0;
  @State end: number = 0;
  @State text: string = '请选择此文字';
  @State isShown: boolean = true;

  getContentLength() {
    return this.text.length;
  }

  setSelection(start: number, end: number) {
    this.start = start;
    this.end = end;
  }

  setAllSelect() {
    this.setSelection(0, this.getContentLength());
  }

  build() {
    Column() {
      Column() {
        TextArea({ text: this.text })
          .fontSize(16)
          .copyOption(CopyOptions.InApp)
          .bindContextMenu(this.isShown, selectionMenu(),
            {
              onDisappear: () => {
                this.isShown = false;
              }
            })
          .editMenuOptions({
            onCreateMenu: () => {
              console.info(`Text onCreateMenu`);
              this.isShown = true;
              return []; // 拦截默认菜单项,显示自定义contextmenu
            }, onMenuItemClick: () => {
              return true;
            }
          })
          .onTextSelectionChange((start, end) => {
            console.info(`TextSelection ${start.toString()} - ${end.toString()}`);
            if (start < 0 || end < 0) {
              this.setSelection(0, 0);
              this.isShown = false;
            } else {
              this.start = start;
              this.end = end;
            }
          })
          .parallelGesture(
            LongPressGesture()
              .onAction(() => {
                this.setAllSelect();
              })
          );
      }
      .padding(50)
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#fff3f2f2')
      .parallelGesture(
        LongPressGesture()
          .onAction(() => {
            this.setAllSelect();
          })
      );
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}

@Builder
function selectionMenu() {
  Column() {
    Text('CustomMenu');
  };
}

方案三:取消editMenuOptions的参数editMenu的菜单选项。

  1. 以禁止粘贴为例,定义onCreateMenu方法,使用filter函数剪切Array中的粘贴选项。
  2. 在editMenuOptions属性中使用onCreateMenu方法初始化editMenu。

示例代码如下:

@Entry
@Component
struct ProhibitLongPressPopupMenuThree {
  @State text: string = 'TextArea editMenuOptions';

  onCreateMenu(menuItems: Array<TextMenuItem>) {
    menuItems = menuItems.filter((item) => item.content !== '粘贴'); // 也可选择禁止输入/全选等其它菜单选项
    return menuItems;
  }

  build() {
    Column() {
      TextArea({ text: this.text })
        .width('95%')
        .height(56)
        .editMenuOptions({
          onCreateMenu: this.onCreateMenu, onMenuItemClick: () => {
            return false; // 返回为false,先执行自定义逻辑,再执行系统逻辑
          }
        })
        .margin({ top: 100 });
    }
    .width('90%')
    .margin('5%');
  }
}

明显的方案特点如下:

SelectionMenuHidden属性隐藏文本选择菜单 拦截整个默认菜单并使用自定义bindContextMenu代替 取消editMenu的菜单选项
实现简单直接,但是只需设置selectionMenuHidden属性即可,过度粗暴,删除了所有文本操作功能,适用于安全性要求极高,允许任何文本操作的场景。 实现最复杂,需要处理菜单显示、交互性等问题,可能会增加吞吐量。优势在于功能灵活且完全可控,能够改装不同的业务场景。 性能和稳定性优异,在选择禁止某项菜单功能的同时保留了其他文本菜单功能。

都说了 那个是图片的识别,控件就是Image图片, 不是text/editer/textArea,所以你这个方案在Image不可行

调整api

setCustomTextMenuItems 更像是增加自定义菜单项,不一定等于完全替换系统选择菜单。若选中的文字最终由你自己的 Text/RichEditor 承载,可以优先看 editMenuOptions 或 TextMenuController 相关能力,拦截/移除 COPY、SELECT_ALL、TRANSLATE 等菜单项。

但如果这是 AI 识图控制器内置的识别浮层,菜单是否能完全屏蔽要看该 controller 是否暴露替换/禁用系统项的接口。没有接口时,不建议用不可控的 DOM/坐标遮挡去“盖住”系统菜单;更稳的是拿识别结果后自己渲染文本层,再在自有 Text/RichEditor 上管理菜单。

控件本身是Image,而且aiController也没有提供可以覆盖textmenu的方法

EditMenuOptions 或 TextMenuController 也试过,无法覆盖菜单的能力

在HarmonyOS Next中,可通过设置组件的selectionMenuOptions属性为空列表或配置menuPolicyMenuPolicy.NONE来屏蔽系统菜单。对于TextRichEditor组件,示例:Text().selectionMenuOptions([])Text().menuPolicy(MenuPolicy.NONE)。若使用自定义菜单,返回空数组即可。

回到顶部