1# 菜单控制 2 3为组件绑定弹出式菜单,弹出式菜单以垂直列表形式显示菜单项,可通过长按、点击或鼠标右键触发。 4 5> **说明:** 6> 7> - 从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8> 9> - CustomBuilder里不支持再使用bindMenu、bindContextMenu弹出菜单。多级菜单可使用[Menu组件](ts-basic-components-menu.md)。 10> 11> - 弹出菜单的文本内容不支持长按选中。 12 13 14## 属性 15 16 17| 名称 | 参数类型 | 描述 | 18| ---------------------------- | ---------------------------------------- | ---------------------------------------- | 19| bindMenu | content: Array<[MenuItem](#menuitem)> \| [CustomBuilder](ts-types.md#custombuilder8),<br>options?: [MenuOptions](#menuoptions10) | 给组件绑定菜单,点击后弹出菜单。弹出菜单项支持图标+文本排列和自定义两种功能。<br/>content: 配置菜单项图标和文本的数组,或者自定义组件。<br/>options: 配置弹出菜单的参数。 | 20| bindContextMenu<sup>8+</sup> | content: [CustomBuilder](ts-types.md#custombuilder8),<br>responseType: [ResponseType](ts-appendix-enums.md#responsetype8)<br>options?: [ContextMenuOptions](#contextmenuoptions10) | 给组件绑定菜单,触发方式为长按或者右键点击,弹出菜单项需要自定义。<br/>responseType: 菜单弹出条件,长按或者右键点击。<br/>options: 配置弹出菜单的参数。 | 21 22## MenuItem 23 24| 名称 | 类型 | 必填 | 描述 | 25| ------------------ | -------------------------------------- | ---- | ---------------------- | 26| value | [ResourceStr](ts-types.md#resourcestr) | 是 | 菜单项文本。 | 27| icon<sup>10+</sup> | [ResourceStr](ts-types.md#resourcestr) | 否 | 菜单项图标。 | 28| action | () => void | 是 | 点击菜单项的事件回调。 | 29 30## MenuOptions<sup>10+</sup> 31 32继承自[ContextMenuOptions](#contextmenuoptions10)。 33 34| 名称 | 类型 | 必填 | 描述 | 35| ----- | ------ | ---- | ------------------------------------------------------------ | 36| title | string | 否 | 菜单标题。<br>**说明:** <br/>仅在content设置为Array<[MenuItem](#menuitem)> 时生效。 | 37 38## ContextMenuOptions<sup>10+</sup> 39 40| 名称 | 类型 | 必填 | 描述 | 41| ----------- | -------------------------------------------- | ---- | ------------------------------------------------------------ | 42| offset | [Position](ts-types.md#position8) | 否 | 菜单弹出位置的偏移量,不会导致菜单显示超出屏幕范围。<br/>**说明:**<br />菜单类型为相对⽗组件区域弹出时,⾃动根据菜单位置属性 (placement)将区域的宽或⾼计⼊偏移量中。<br/>当菜单相对父组件出现在上侧时(placement设置为Placement.TopLeft,Placement.Top,Placement.TopRight),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向上进行偏移。<br/>当菜单相对父组件出现在下侧时(placement设置为Placement.BottomLeft,Placement.Bottom,Placement.BottomRight),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>当菜单相对父组件出现在左侧时(placement设置为Placement.LeftTop,Placement.Left,Placement.LeftBottom),x为正值,菜单相对组件向左进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>当菜单相对父组件出现在右侧时(placement设置为Placement.RightTop,Placement.Right,Placement.RightBottom),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>如果菜单调整了显示位置(与placement初始值主方向不⼀致),则偏移值 (offset) 失效。 | 43| placement | [Placement](ts-appendix-enums.md#placement8) | 否 | 菜单组件优先显示的位置,当前位置显示不下时,会自动调整位置。<br/>**说明:**<br />placement值设置为undefined、null或没有设置此选项时,按未设置placement处理,菜单跟随点击位置弹出。 | 44| enableArrow | boolean | 否 | 是否显示箭头。如果菜单的大小和位置不足以放置箭头时,不会显示箭头。 <br/>默认值:false, 不显示箭头。<br/>**说明:**<br />enableArrow为true时,placement未设置或者值为非法值,默认在目标物上方显示,否则按照placement的位置优先显示。当前位置显示不下时,会自动调整位置,enableArrow为undefined时,不显示箭头。 | 45| arrowOffset | [Length](ts-types.md#length) | 否 | 箭头在菜单处的偏移。箭头在菜单水平方向时,偏移量为箭头至最左侧的距离,默认居中。箭头在菜单竖直方向时,偏移量为箭头至最上侧的距离,默认居中。偏移量必须合法且转换为具体数值时大于0才会生效,另外该值生效时不会导致箭头超出菜单四周的安全距离。根据配置的placement来计算是在水平还是竖直方向上偏移。 | 46| onAppear | () => void | 否 | 菜单弹出时的事件回调。 | 47| onDisappear | () => void | 否 | 菜单消失时的事件回调。 | 48 49## 示例 50 51### 示例1 52 53普通菜单 54 55```ts 56// xxx.ets 57@Entry 58@Component 59struct MenuExample { 60 build() { 61 Column() { 62 Text('click for Menu') 63 } 64 .width('100%') 65 .margin({ top: 5 }) 66 .bindMenu([ 67 { 68 value: 'Menu1', 69 action: () => { 70 console.info('handle Menu1 select') 71 } 72 }, 73 { 74 value: 'Menu2', 75 action: () => { 76 console.info('handle Menu2 select') 77 } 78 }, 79 ]) 80 } 81} 82``` 83 84 85 86### 示例2 87 88自定义内容菜单 89 90```ts 91@Entry 92@Component 93struct MenuExample { 94 @State listData: number[] = [0, 0, 0] 95 96 @Builder MenuBuilder() { 97 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 98 ForEach(this.listData, (item:number, index) => { 99 Column() { 100 Row() { 101 Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 }) 102 Text(`Menu${index as number + 1}`).fontSize(20) 103 } 104 .width('100%') 105 .height(30) 106 .justifyContent(FlexAlign.Center) 107 .align(Alignment.Center) 108 .onClick(() => { 109 console.info(`Menu${index as number + 1} Clicked!`) 110 }) 111 112 if (index != this.listData.length - 1) { 113 Divider().height(10).width('80%').color('#ccc') 114 } 115 }.padding(5).height(40) 116 }) 117 }.width(100) 118 } 119 120 build() { 121 Column() { 122 Text('click for menu') 123 .fontSize(20) 124 .margin({ top: 20 }) 125 .bindMenu(this.MenuBuilder) 126 } 127 .height('100%') 128 .width('100%') 129 .backgroundColor('#f0f0f0') 130 } 131} 132``` 133 134 135 136### 示例3 137 138菜单(长按触发显示) 139 140```ts 141// xxx.ets 142@Entry 143@Component 144struct ContextMenuExample { 145 @Builder MenuBuilder() { 146 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 147 Text('Test menu item 1') 148 .fontSize(20) 149 .width(100) 150 .height(50) 151 .textAlign(TextAlign.Center) 152 Divider().height(10) 153 Text('Test menu item 2') 154 .fontSize(20) 155 .width(100) 156 .height(50) 157 .textAlign(TextAlign.Center) 158 }.width(100) 159 } 160 161 build() { 162 Column() { 163 Text('LongPress for menu') 164 } 165 .width('100%') 166 .margin({ top: 5 }) 167 .bindContextMenu(this.MenuBuilder, ResponseType.LongPress) 168 } 169} 170``` 171 172 173 174### 示例4 175 176指向性菜单(右键触发显示) 177 178```ts 179// xxx.ets 180@Entry 181@Component 182struct DirectiveMenuExample { 183 @Builder MenuBuilder() { 184 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 185 Text('Options') 186 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 187 Text('Hide') 188 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 189 Text('Exit') 190 } 191 .width(200) 192 } 193 194 build() { 195 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 196 Column() { 197 Text("DirectiveMenuExample") 198 .fontSize(20) 199 .width('100%') 200 .height("25%") 201 .backgroundColor('#F0F0F0') 202 .textAlign(TextAlign.Center) 203 .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, { 204 enableArrow: true, 205 placement: Placement.Bottom 206 }) 207 } 208 } 209 .width('100%') 210 .height('100%') 211 } 212} 213``` 214 215 216