1# Menu Control 2 3A context menu – a vertical list of items – can be bound to a component and displayed by long-pressing, clicking, or right-clicking the component. 4 5> **NOTE** 6> 7> - The APIs of this module are supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version. 8> 9> - **CustomBuilder** does not support the use of **bindMenu** and **bindContextMenu** methods. To display a multi-level menu, use the [\<Menu>](ts-basic-components-menu.md) component instead. 10 11 12## Attributes 13 14 15| Name | Type | Description | 16| ---------------------------- | ---------------------------------------- | ---------------------------------------- | 17| bindMenu | content: Array<[MenuItem](#menuitem)> \| [CustomBuilder](ts-types.md#custombuilder8),<br>options?: [MenuOptions](#menuoptions10) | Menu bound to the component, which is displayed when the user clicks the component. A menu item can be a combination of text and icons or a custom component.<br>**content**: array of menu item icons and text, or custom component.<br>**options**: parameters of the context menu.| 18| bindContextMenu<sup>8+</sup> | content: [CustomBuilder](ts-types.md#custombuilder8),<br>responseType: [ResponseType](ts-appendix-enums.md#responsetype8)<br>options?: [ContextMenuOptions](#contextmenuoptions10) | Context menu bound to the component, which is displayed when the user long-presses or right-clicks the component. Only custom menu items are supported.<br>**responseType**: how the context menu is triggered, which can be long-press or right-click.<br>**options**: parameters of the context menu.| 19 20## MenuItem 21 22| Name | Type | Mandatory | Description | 23| ------------------ | -------------------------------------- | ---- | ----------- | 24| value | string | Yes | Menu item text. | 25| icon<sup>10+</sup> | [ResourceStr](ts-types.md#resourcestr) | No | Menu item icon. | 26| action | () => void | Yes | Action triggered when a menu item is clicked.| 27 28## MenuOptions<sup>10+</sup> 29 30| Name | Type | Mandatory| Description | 31| ----------- | -------------------------------------------- | ---- | ------------------------------------------------------------ | 32| title | string | No | Menu title.<br>**NOTE**<br>This parameter is available only when **content** is set to Array<[MenuItem](#menuitem)>.| 33| offset | [Position](ts-types.md#position8) | No | Offset for showing the context menu, which should not cause the menu to extend beyond the screen.<br>**NOTE**<br>When the menu is displayed relative to the parent component area, the width or height of the area is automatically counted into the offset based on the **placement** attribute of the menu.<br>When the menu is displayed above the parent component (that is, **placement** is set to **Placement.TopLeft**, **Placement.Top**, or **Placement.TopRight**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates upward movement.<br>When the menu is displayed below the parent component (that is, **placement** is set to **Placement.BottomLeft**, **Placement.Bottom**, or **Placement.BottomRight**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>When the menu is displayed on the left of the parent component (that is, **placement** is set to **Placement.LeftTop**, **Placement.Left**, or **Placement.LeftBottom**), a positive value of **x** indicates leftward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>When the menu is displayed on the right of the parent component (that is, **placement** is set to **Placement.RightTop**, **Placement.RightTop**, or **Placement.RightBottom**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>If the display position of the menu is adjusted (different from the main direction of the initial **placement** value), the offset value is invalid.| 34| placement | [Placement](ts-appendix-enums.md#placement8) | No | Preferred position of the context menu. If the set position is insufficient for holding the component, it will be automatically adjusted.<br>**NOTE**<br>If **placement** is set to **undefined** or **null** or is not set, the default value [BottomLeft](ts-appendix-enums.md#placement8) is used, and the position is relative to the parent component.| 35| onAppear | () => void | No | Callback triggered when the menu is displayed. | 36| onDisappear | () => void | No | Callback triggered when the menu is hidden. | 37 38## ContextMenuOptions<sup>10+</sup> 39 40| Name | Type | Mandatory| Description | 41| ----------- | -------------------------------------------- | ---- | ------------------------------------------------------------ | 42| offset | [Position](ts-types.md#position8) | No | Offset for showing the context menu, which should not cause the menu to extend beyond the screen.<br>**NOTE**<br>When the menu is displayed relative to the parent component area, the width or height of the area is automatically counted into the offset based on the **placement** attribute of the menu.<br>When the menu is displayed above the parent component (that is, **placement** is set to **Placement.TopLeft**, **Placement.Top**, or **Placement.TopRight**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates upward movement.<br>When the menu is displayed below the parent component (that is, **placement** is set to **Placement.BottomLeft**, **Placement.Bottom**, or **Placement.BottomRight**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>When the menu is displayed on the left of the parent component (that is, **placement** is set to **Placement.LeftTop**, **Placement.Left**, or **Placement.LeftBottom**), a positive value of **x** indicates leftward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>When the menu is displayed on the right of the parent component (that is, **placement** is set to **Placement.RightTop**, **Placement.RightTop**, or **Placement.RightBottom**), a positive value of **x** indicates rightward movement relative to the parent component, and a positive value of **y** indicates downward movement.<br>If the display position of the menu is adjusted (different from the main direction of the initial **placement** value), the offset value is invalid.| 43| placement | [Placement](ts-appendix-enums.md#placement8) | No | Preferred position of the context menu. If the set position is insufficient for holding the component, it will be automatically adjusted.<br>**NOTE**<br>Setting **placement** to **undefined** or **null** is equivalent to not setting it at all, and the context menu is displayed where the mouse is clicked.| 44| enableArrow | boolean | No | Whether to display an arrow. If the size and position of the context menu are insufficient for holding an arrow, no arrow is displayed.<br>Default value: **false**, indicating that no arrow is displayed<br>**NOTE**<br>An arrow is displayed in the position specified by **placement**. If **placement** is not set or its value is invalid, the arrow is displayed above the target. If the position is insufficient for holding the arrow, it is automatically adjusted.| 45| arrowOffset | [Length](ts-types.md#length) | No | Offset of the arrow relative to the context menu. When the arrow is placed in a horizontal position with the context menu: The value indicates the distance from the arrow to the leftmost; the arrow is centered by default. When the arrow is placed in a vertical position with the context menu: The value indicates the distance from the arrow to the top; the arrow is centered by default. The offset settings take effect only when the value is valid, can be converted to a number greater than 0, and does not cause the arrow to extend beyond the safe area of the context menu. The value of **placement** determines whether the offset is horizontal or vertical.| 46| onAppear | () => void | No | Callback triggered when the menu is displayed. | 47| onDisappear | () => void | No | Callback triggered when the menu is hidden. | 48 49## Example 50 51### Example 1 52 53Menu with Textual Menu Items 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### Example 2 87 88Menu with Custom Menu Items 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### Example 3 137 138Context Menu (Displayed Upon Right-Click) 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('rightclick for menu') 164 } 165 .width('100%') 166 .margin({ top: 5 }) 167 .bindContextMenu(this.MenuBuilder, ResponseType.RightClick) 168 } 169} 170``` 171 172### Example 4 173 174Directive Menu (Displayed Upon Right-Click) 175 176```ts 177// xxx.ets 178@Entry 179@Component 180struct DirectiveMenuExample { 181 @Builder MenuBuilder() { 182 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 183 Text('Options') 184 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 185 Text('Hide') 186 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 187 Text('Exit') 188 } 189 .width(200) 190 } 191 192 build() { 193 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 194 Column() { 195 Text("DirectiveMenuExample") 196 .fontSize(20) 197 .width('100%') 198 .height("25%") 199 .backgroundColor('#F0F0F0') 200 .textAlign(TextAlign.Center) 201 .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, { 202 enableArrow: true, 203 placement: Placement.Bottom 204 }) 205 } 206 } 207 .width('100%') 208 .height('100%') 209 } 210} 211``` 212 213 214