• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>  - The text in the context menu cannot be selected by long-pressing.
12
13
14## Attributes
15
16
17| Name                          | Type                                    | Description                                      |
18| ---------------------------- | ---------------------------------------- | ---------------------------------------- |
19| bindMenu                     | content: Array<[MenuItem](#menuitem)&gt; \| [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.|
20| 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.|
21
22## MenuItem
23
24| Name                | Type                                    | Mandatory  | Description         |
25| ------------------ | -------------------------------------- | ---- | ----------- |
26| value              | [ResourceStr](ts-types.md#resourcestr)                                 | Yes   | Menu item text.     |
27| icon<sup>10+</sup> | [ResourceStr](ts-types.md#resourcestr) | No   | Menu item icon.     |
28| action             | () =&gt; void                | Yes   | Action triggered when a menu item is clicked.|
29
30## MenuOptions<sup>10+</sup>
31
32Inherited from [ContextMenuOptions](#contextmenuoptions10).
33
34| Name       | Type                                        | Mandatory| Description                                                        |
35| ----------- | -------------------------------------------- | ---- | ------------------------------------------------------------ |
36| title       | string                                       | No  | Menu title.<br>**NOTE**<br>This parameter is available only when **content** is set to Array<[MenuItem](#menuitem)>.|
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>When **enableArrow** is **true**, 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. When **enableArrow** is **undefined**, no arrow is displayed.|
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    | () =&gt; void                                | No  | Callback triggered when the menu is displayed.                                      |
47| onDisappear | () =&gt; 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![en_image_0000001174582862](figures/en_image_0000001174582862.gif)
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![en_image_0000001186807708](figures/en_image_0000001186807708.gif)
135
136### Example 3
137
138Context Menu Displayed Upon Long-Pressing
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![longMenu](figures/longMenu.gif)
173
174### Example 4
175
176Directive Menu Displayed Upon Right-Click
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![en-us_image_0000001689126950](figures/en-us_image_0000001689126950.png)
216