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(value: CopyOptions)用于设置组件是否支持文本可复制粘贴。设置copyOptions为copyOption.InApp或者copyOption.LocalDevice,长按文本,会弹出文本选择菜单,可选中文本并进行复制、全选操作。
-
用于触发长按手势事件,触发长按手势的最少手指个数为1,最短长按时间为500毫秒。
【定位思路】
-
设置变量customPopup,将customPopup的值显示在桌面,在LongPressGesture事件onActionEnd的回调函数中改变customPopup的值。长按文本,发现文本处于全选状态,只能展示系统的“复制”弹窗,不能展示自定义弹窗。定位发现customPopup的值没有变化,且LongPressGesture事件没有触发,现象如上图。
-
考虑使用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弹窗。
- 首先创建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
}
})
- 设置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
更多关于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
实现全选和自定义弹窗同时出现。