HarmonyOS鸿蒙Next中如何屏蔽或者重写TextInput的文本选择菜单的复制、粘贴功能?

HarmonyOS鸿蒙Next中如何屏蔽或者重写TextInput的文本选择菜单的复制、粘贴功能? 如上图,我想重写复制和粘贴的功能,如何实现呢?涉及的API文档具体是哪个?

image.png


更多关于HarmonyOS鸿蒙Next中如何屏蔽或者重写TextInput的文本选择菜单的复制、粘贴功能?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

开发者您好,

TextInput、TextArea等文本输入组件,在长按时会自动弹起系统文本选择菜单;

如果想要隐藏系统文本选择菜单,可以使用selectionMenuHidden属性进行隐藏。

如果不想隐藏系统文本选择菜单,而是仅仅想禁止粘贴,有以下两种方法:

  • 重写onPaste方法,在触发粘贴事件回调时不让文本粘贴。
  • 使用editMenuOptions设置自定义菜单的扩展项,禁用editMenu的粘贴项。

使用自定义菜单bindContextMenu替代系统文本选择菜单,isShownfalse时,隐藏菜单。弹出菜单项需要自定义。

推荐解决方案:

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

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

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

方案二:在TextInputonPaste回调事件中阻止文本的粘贴,示例代码如下:

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

  build() {
    Column() {
      Text(`输入的内容: ${this.message}`).margin({ top: 100, bottom: 30 })
      TextInput({ placeholder: "请输入内容" })
        .borderRadius(0)
        .onChange((value: string) => {
          this.message = value
        })
        .onPaste((value: string, event: PasteEvent) => {
          if (event !== undefined && event.preventDefault) {
            console.info("禁止粘贴")
            event.preventDefault()
          }
        })
    }
    .height('100%')
    .width('100%')
  }
}

方案三:禁用editMenu粘贴项。

  • 定义onCreateMenu方法,使用filter函数切除Array<TextMenuItem>中的粘贴项。
  • editMenuOptions属性中使用onCreateMenu方法初始化editMenu

示例代码如下:

@Entry
@Component
struct TextAreaExample {
  @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: (menuItem: TextMenuItem, textRange: TextRange) => {
            return false;
          }
        })
        .margin({ top: 100 })
    }
    .width("90%")
    .margin("5%")
  }
}

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

  • Array<TextMenuItem>返回空数组,从而拦截整个editMenu
  • 定义bindContextMenu,实际内容和功能需要自定义。

示例代码如下:

@Entry
@Component
struct Example {
  @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: (menuItems: Array<TextMenuItem>) => {
              console.log(`Text onCreateMenu ----------------------`)
              this.isShown = true
              return [] // 拦截默认菜单项,显示自定义contextmenu
            }, onMenuItemClick: (menuItem: TextMenuItem, textRange: TextRange) => {
              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((event: GestureEvent) => {
                this.setAllSelect()
              })
          )
      }
      .padding(50)
      .justifyContent(FlexAlign.Center)
      .backgroundColor(Color.Pink)
      .parallelGesture(
        LongPressGesture()
          .onAction((event: GestureEvent) => {
            this.setAllSelect()
          })
      )
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

@Builder
function SelectionMenu() {
  Column() {
    Text('CustomMenu')
  }
}

更多关于HarmonyOS鸿蒙Next中如何屏蔽或者重写TextInput的文本选择菜单的复制、粘贴功能?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


if (TextMenuItemId.of(‘自定义’).equals(menuItem.id)) { return true }


我用 == 号比较,它也没报错,定位了老半天

你好。这里是跨设备剪贴板开发文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/distributed-pasteboard-guide。希望可以帮助到你。

总的来说,HarmonyOS是一款非常优秀的操作系统,期待它能在未来带给我们更多惊喜!

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md#editmenuoptions12

有这么一个接口可以用,亲测有效

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Column() {
      TextInput().width('100%').editMenuOptions({
        onCreateMenu: (menuItems: Array<TextMenuItem>) => {
          // 入参是包含了所有系统菜单的信息,可以修改这个数组,最终系统会根据这个列表添加选项
          // 如你标题所示,如果你想屏蔽复制按钮可以这么写
          menuItems.filter((item: TextMenuItem) => {
            return item.id == TextMenuItemId.COPY
          })
          // 如果你要添加一个控制选项
          menuItems.push({
            id: TextMenuItemId.of('自定义'),
            content: '自定义按钮'
          })
          return menuItems
        },
        onMenuItemClick: (menuItem: TextMenuItem, range: TextRange) => {
          // 这个接口在每个按钮按下的时候会触发,看参数很好理解,如果你添加了一个自定义按钮,这里可以写你自己的业务逻辑
          if (menuItem.id == TextMenuItemId.of('自定义')) {
            return true
          }
          // 这个返回值true表示按钮逻辑处理完了,对于系统原有的菜单,这里返回true表示应用侧处理完了,不需要系统的默认处理逻辑了
          // 所以,你要自己重写系统的粘贴功能,就可以在这里实现
          if (menuItem.id == TextMenuItemId.PASTE) {
            // 自己实现粘贴功能,所谓粘贴无非就是把剪切板里的数据拿出来,再通过状态变量塞回去,注意访问剪切需要申请权限的
            // 实测系统自带的粘贴好像不要申请,感觉是加了白名单控制??
            return true
          }
          return true
        }
      })
    }
    .width('100%').borderWidth(1)
  }
}

在HarmonyOS鸿蒙Next中,可以通过重写TextInput组件的onTextContextMenu方法来屏蔽或自定义文本选择菜单的复制、粘贴功能。具体步骤如下:

  1. 创建一个自定义的TextInput组件。
  2. 在组件中重写onTextContextMenu方法。
  3. onTextContextMenu方法中,根据需求过滤掉“复制”和“粘贴”选项,或者自定义菜单项。

示例代码:

class CustomTextInput extends TextInput {
  onTextContextMenu(event) {
    const menuItems = event.menuItems.filter(item => item.label !== '复制' && item.label !== '粘贴');
    event.menuItems = menuItems;
    super.onTextContextMenu(event);
  }
}

通过这种方式,你可以灵活控制文本选择菜单的行为。

回到顶部