HarmonyOS鸿蒙Next中如何解决Text组件copyOption全选和自定义弹窗无法同时出现的问题

HarmonyOS鸿蒙Next中如何解决Text组件copyOption全选和自定义弹窗无法同时出现的问题

【问题现象】

使用Text组件copyOption属性,希望实现长按文本全部选中效果,并且弹出自定义弹窗,弹窗使用bindPopup实现,此方案的问题:只能弹出文本选择浮标,无法弹出自定义弹窗。

核心代码如下:

@Builder
popupBuilder() {
  Column({ space: 2 }) {
    Text('这是一个popup弹窗')
      .fontSize(10)
  }
  .justifyContent(FlexAlign.SpaceAround)
  .width(100)
  .height(100)
  .padding(5)
}

@Component
struct child {
  @Link customPopup: boolean
  build() {
    Column({ space: 10 }) {
      Text(JSON.stringify(this.customPopup))
      Text('这是一段用于复制的文本')
        .copyOption(CopyOptions.InApp)
        .borderWidth(1)
        .gesture(
          LongPressGesture({ repeat: true })
            .onActionEnd((event: GestureEvent) => {
              this.customPopup = !this.customPopup
            })
        )
    }
  }
}

现象截图如下:

点击放大

【背景知识】

  • copyOption属性的使用

    copyOption(value: CopyOptions)用于设置组件是否支持文本可复制粘贴。设置copyOptions为copyOption.InApp或者copyOption.LocalDevice,长按文本,会弹出文本选择菜单,可选中文本并进行复制、全选操作。

  • LongPressGesture事件

    用于触发长按手势事件,触发长按手势的最少手指个数为1,最短长按时间为500毫秒。

【定位思路】

  1. 设置变量customPopup,将customPopup的值显示在桌面,在LongPressGesture事件onActionEnd的回调函数中改变customPopup的值。长按文本,发现文本处于全选状态,只能展示系统的“复制”弹窗,不能展示自定义弹窗。定位发现customPopup的值没有变化,且LongPressGesture事件没有触发,现象如上图。

  2. 考虑使用priorityGesture替代gesture,长按可进入全选状态,同时可以弹出自定义弹窗,但是,此时也会展示系统自带的“复制”弹窗,不符合要求,见下图:

build() {
  Column({ space: 10 }) {
    Text(JSON.stringify(this.customPopup))
    Text(this.text)
      .copyOption(CopyOptions.InApp)
      .selection(this.textStart, this.textEnd)
      .borderWidth(1)
      .priorityGesture(
        LongPressGesture({ repeat: true }) // 由于repeat设置为true,长按动作存在时会连续触发,触发间隔为duration(默认值500ms)
          .onActionEnd((event: GestureEvent) => {
            this.customPopup = !this.customPopup
            this.textStart = 0
            this.textEnd = this.text.length
          })
      )
  }
}

点击放大

经上述定位,发现使用copyOption和长按手势的方案,无法实现长按文本全部选中,并且只弹出自定义弹窗的效果。

【解决方案】

可使用Text 的bindSelectionMenu属性,设置自定义选择菜单,替代bindPopup弹窗。

  1. 首先创建Text组件,并设置bindSelectionMenu属性,用于弹出自定义弹窗,核心代码如下:
Text(undefined, this.options) {
  Span(this.text)
}
.copyOption(CopyOptions.InApp)
.selection(this.textStart, this.textEnd)
// 核心修改:在此处添加RightClickTextCustomMenu
.bindSelectionMenu(TextSpanType.TEXT, this.RightClickTextCustomMenu, TextResponseType.LONG_PRESS, {
  onDisappear: () => {
    console.info(`自定义选择菜单关闭时回调`);
    this.textStart = 0
    this.textEnd = 0
  },
  onAppear: () => {
    console.info(`自定义选择菜单弹出时回调`);
    this.textStart = 0
    this.textEnd = this.text.length
  }
})
  1. 设置bindSelectionMenu的入参RightClickTextCustomMenu,作为展示的菜单内容,核心代码如下:
@Builder
RightClickTextCustomMenu() {
  Column() {
    Menu() {
      MenuItemGroup() {
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 1", labelInfo: "" })
          .onClick((event) => {
            this.controller.closeSelectionMenu();
          })
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 2", labelInfo: "" })
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 3", labelInfo: "" })
      }
    }
    .MenuStyles()
  }
}

按照如上步骤设置后,实现的效果如下图所示,可以实现全选的同时,弹出自定义弹窗“Right Click Menu”:

点击放大


更多关于HarmonyOS鸿蒙Next中如何解决Text组件copyOption全选和自定义弹窗无法同时出现的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中如何解决Text组件copyOption全选和自定义弹窗无法同时出现的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


使用Text组件的bindSelectionMenu属性替代bindPopup,实现长按文本全选并弹出自定义弹窗。核心代码如下:

Text(undefined, this.options) {
  Span(this.text)
}
.copyOption(CopyOptions.InApp)
.selection(this.textStart, this.textEnd)
.bindSelectionMenu(TextSpanType.TEXT, this.RightClickTextCustomMenu, TextResponseType.LONG_PRESS, {
  onDisappear: () => {
    console.info(`自定义选择菜单关闭时回调`);
    this.textStart = 0;
    this.textEnd = 0;
  },
  onAppear: () => {
    console.info(`自定义选择菜单弹出时回调`);
    this.textStart = 0;
    this.textEnd = this.text.length;
  }
})

自定义菜单内容:

@Builder
RightClickTextCustomMenu() {
  Column() {
    Menu() {
      MenuItemGroup() {
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 1", labelInfo: "" })
          .onClick((event) => {
            this.controller.closeSelectionMenu();
          })
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 2", labelInfo: "" })
        MenuItem({ startIcon: $r('app.media.app_icon'), content: "Right Click Menu 3", labelInfo: "" })
      }
    }
    .MenuStyles()
  }
}

通过bindSelectionMenu实现全选和自定义弹窗同时出现。

回到顶部