Text是文本组件,用于展示用户视图,如显示文章的文字内容。该组件支持绑定自定义文本选择菜单,用户可根据需要选择不同功能。此外,还可以扩展自定义菜单,丰富可用选项,进一步提升用户体验。
设置选中菜单
弹出选中菜单
设置Text被选中时,会弹出包含复制、翻译、搜索的菜单。 Text组件需要设置copyOption属性才可以被选中。
typescript
@Entry
@Component
struct Index {
build() {
Column() {
Text("这是一段文本,用来展示选中菜单")
.fontSize(30)
.copyOption(CopyOptions.InApp)
}.width('100%').height('100%')
}
}

Text组件通过设置bindSelectionMenu属性绑定自定义选择菜单。
typescript
@Entry
@Component
struct Index {
controller:TextController = new TextController()
build() {
Column() {
Text("这是一段文本,用来展示选中菜单", {controller:this.controller})
.fontSize(30)
.copyOption(CopyOptions.InApp)
.bindSelectionMenu(TextSpanType.TEXT, this.RightClickTextCustomMenu, TextResponseType.RIGHT_CLICK, {
onAppear: () => {
console.info('自定义选择菜单弹出时触发该回调');
},
onDisappear: () => {
console.info('自定义选择菜单关闭时触发该回调');
}
})
}.width('100%').height('100%')
}
@Builder
RightClickTextCustomMenu() {
Column() {
Menu() {
MenuItemGroup() {
MenuItem({ startIcon: $r('app.media.app_icon'), content: "CustomMenu One", labelInfo: "" })
.onClick(() => {
this.controller.closeSelectionMenu();
})
MenuItem({ startIcon: $r('app.media.app_icon'), content: "CustomMenu Two", labelInfo: "" })
MenuItem({ startIcon: $r('app.media.app_icon'), content: "CustomMenu Three", labelInfo: "" })
}
}.backgroundColor('#F0F0F0')
}
}
}

Text组件通过设置editMenuOptions属性扩展自定义选择菜单,可以设置扩展项的文本内容、图标以及回调方法。
typescript
@Entry
@Component
struct Index {
onCreateMenu = (menuItems: Array<TextMenuItem>) => {
let item1: TextMenuItem = {
content: 'customMenu1',
icon: $r('app.media.app_icon'),
id: TextMenuItemId.of('customMenu1'),
};
let item2: TextMenuItem = {
content: 'customMenu2',
id: TextMenuItemId.of('customMenu2'),
icon: $r('app.media.app_icon'),
};
menuItems.push(item1);
menuItems.unshift(item2);
return menuItems;
}
onMenuItemClick = (menuItem: TextMenuItem, textRange: TextRange) => {
if (menuItem.id.equals(TextMenuItemId.of("customMenu2"))) {
console.info("拦截 id: customMenu2 start:" + textRange.start + "; end:" + textRange.end);
return true;
}
if (menuItem.id.equals(TextMenuItemId.COPY)) {
console.info("拦截 COPY start:" + textRange.start + "; end:" + textRange.end);
return true;
}
if (menuItem.id.equals(TextMenuItemId.SELECT_ALL)) {
console.info("不拦截 SELECT_ALL start:" + textRange.start + "; end:" + textRange.end);
return false;
}
return false;
};
build() {
Column() {
Text('这是一段文本,用来展示选中菜单')
.fontSize(20)
.copyOption(CopyOptions.LocalDevice)
.editMenuOptions({
onCreateMenu: this.onCreateMenu, onMenuItemClick: this.onMenuItemClick
})
}.width('100%').height('100%')
}
}

关闭选中菜单
使用Text组件时,若需要实现点击空白处关闭选中的场景,分为以下两种情况:
- 在Text组件区域内点击空白处,会正常关闭选中态和菜单;
- 在Text组件区域外点击空白处,前提是Text组件设置selection属性,具体示例如下:
typescript
@Entry
@Component
struct Index {
@State text: string =
'This is set selection to Selection text content This is set selection to Selection text content.';
@State start: number = 0;
@State end: number = 20;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {
Text(this.text)
.fontSize(12)
.border({ width: 1 })
.lineHeight(20)
.margin(30)
.copyOption(CopyOptions.InApp)
.selection(this.start, this.end)
.onTextSelectionChange((selectionStart, selectionEnd) => {
this.start = selectionStart;
this.end = selectionEnd;
})
}
.height(600)
.width(335)
.borderWidth(1)
.onClick(() => {
this.start = -1;
this.end = -1;
})
}
}
屏蔽系统服务类菜单
从API version 20开始,支持通过disableSystemServiceMenuItems屏蔽文本选择菜单内所有系统服务菜单项。
typescript
import { TextMenuController } from '@kit.ArkUI';
@Entry
@Component
struct Index {
aboutToAppear() {
TextMenuController.disableSystemServiceMenuItems(true);
}
aboutToDisappear() {
TextMenuController.disableSystemServiceMenuItems(false);
}
build() {
Row() {
Column() {
Text("这是一段文本,长按弹出文本选择菜单")
.height(60)
.fontStyle(FontStyle.Italic)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.copyOption(CopyOptions.InApp)
.editMenuOptions({
onCreateMenu: (menuItems: Array<TextMenuItem>) => {
return menuItems;
},
onMenuItemClick: (menuItem: TextMenuItem, textRange: TextRange) => {
return false;
}
})
}.width('100%')
}
.height('100%')
}
}
从API version 20开始,支持通过disableMenuItems屏蔽文本选择菜单内指定的系统服务菜单项。
typescript
import { TextMenuController } from '@kit.ArkUI'
@Entry
@Component
struct Index {
aboutToAppear() {
TextMenuController.disableMenuItems([TextMenuItemId.SEARCH])
}
aboutToDisappear() {
TextMenuController.disableMenuItems([])
}
build() {
Row() {
Column() {
Text("这是一段文本,长按弹出文本选择菜单")
.height(60)
.fontStyle(FontStyle.Italic)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.copyOption(CopyOptions.InApp)
.editMenuOptions({
onCreateMenu: (menuItems: Array<TextMenuItem>) => {
return menuItems;
},
onMenuItemClick: (menuItem: TextMenuItem, textRange: TextRange) => {
return false
}
})
}.width('100%')
}
.height('100%')
}
}

默认菜单支持自定义刷新能力
从API version 20开始,当文本选择区域变化后显示菜单之前触发onPrepareMenu回调,可在该回调中进行菜单数据设置。
typescript
@Entry
@Component
struct Index {
@State text: string = 'Text editMenuOptions';
@State endIndex: number = 0;
onCreateMenu = (menuItems: Array<TextMenuItem>) => {
let item1: TextMenuItem = {
content: 'create1',
icon: $r('app.media.startIcon'),
id: TextMenuItemId.of('create1'),
};
let item2: TextMenuItem = {
content: 'create2',
id: TextMenuItemId.of('create2'),
icon: $r('app.media.startIcon'),
};
menuItems.push(item1);
menuItems.unshift(item2);
return menuItems;
}
onMenuItemClick = (menuItem: TextMenuItem, textRange: TextRange) => {
if (menuItem.id.equals(TextMenuItemId.of("create2"))) {
console.info("拦截 id: create2 start:" + textRange.start + "; end:" + textRange.end);
return true;
}
if (menuItem.id.equals(TextMenuItemId.of("prepare1"))) {
console.info("拦截 id: prepare1 start:" + textRange.start + "; end:" + textRange.end);
return true;
}
if (menuItem.id.equals(TextMenuItemId.COPY)) {
console.info("拦截 COPY start:" + textRange.start + "; end:" + textRange.end);
return true;
}
if (menuItem.id.equals(TextMenuItemId.SELECT_ALL)) {
console.info("不拦截 SELECT_ALL start:" + textRange.start + "; end:" + textRange.end);
return false;
}
return false;
}
onPrepareMenu = (menuItems: Array<TextMenuItem>) => {
let item1: TextMenuItem = {
content: 'prepare1_' + this.endIndex,
icon: $r('app.media.startIcon'),
id: TextMenuItemId.of('prepare1'),
};
menuItems.unshift(item1);
return menuItems;
}
@State editMenuOptions: EditMenuOptions = {
onCreateMenu: this.onCreateMenu,
onMenuItemClick: this.onMenuItemClick,
onPrepareMenu: this.onPrepareMenu
};
build() {
Column() {
Text(this.text)
.fontSize(20)
.copyOption(CopyOptions.LocalDevice)
.editMenuOptions(this.editMenuOptions)
.margin({ top: 100 })
.onTextSelectionChange((selectionStart: number, selectionEnd: number) => {
this.endIndex = selectionEnd;
})
}
.width("90%")
.margin("5%")
}
}

设置AI菜单
Text组件通过enableDataDetector和dataDetectorConfig属性实现AI菜单的显示。AI菜单的表现形式包括:单击AI实体(指可被识别的内容,包括地址、邮箱等)弹出菜单的实体识别选项,选中文本后,文本选择菜单与鼠标右键菜单中显示的实体识别选项。
说明
从API version 20开始,支持在文本选择菜单与鼠标右键菜单中显示实体识别选项。当enableDataDetector设置为true,且copyOption设置为CopyOptions.LocalDevice时,该功能生效。菜单选项包括TextMenuItemId中的url(打开链接)、email(新建邮件)、phoneNumber(呼叫)、address(导航至该位置)、dateTime(新建日程提醒)。
该功能生效时,需选中范围内,包括一个完整的AI实体,才能展示对应的选项。
- 如果需要单击AI实体弹出菜单的实体识别选项,可以配置enableDataDetector为true。
- 如果在单击的交互方式之外,还需要文本选择菜单与鼠标右键菜单中显示的实体识别选项,可以配置enableDataDetector为true,且copyOption设置为CopyOptions.LocalDevice,具体示例如下所示:
typescript
@Entry
@Component
struct Index {
build() {
Column() {
Text(
'电话号码:' + '(86) (755) ********' + '\n' +
'链接:' + 'www.********.com' + '\n' +
'邮箱:' + '***@example.com' + '\n' +
'地址:' + 'XX省XX市XX区XXXX' + '\n' +
'时间:' + 'XX年XX月XX日XXXX'
)
.fontSize(16)
.copyOption(CopyOptions.LocalDevice)
.enableDataDetector(true)// 使能实体识别
.dataDetectorConfig({
// 配置识别样式
// types可支持PHONE_NUMBER电话号码、URL链接、EMAIL邮箱、ADDRESS地址、DATE_TIME时间
// types设置为null或者[]时,识别所有类型的实体
types: [], onDetectResultUpdate: (result: string) => {
}
})
}.width('100%').height('100%')
}
}
- 如果需要调整识别出的样式,可以通过dataDetectorConfig实现,具体可以参考TextDataDetectorConfig配置项。
- 如果需要调整菜单的位置,可以通过editMenuOptions实现,具体可以参考示例文本扩展自定义菜单。
