• 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## bindMenu
14
15bindMenu(content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
16
17Menu 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.
18
19**System capability**: SystemCapability.ArkUI.ArkUI.Full
20
21**Parameters**
22
23| Name | Type                                                        | Mandatory| Description                                        |
24| ------- | ------------------------------------------------------------ | ---- | -------------------------------------------- |
25| content | Array<[MenuElement](#menuelement)&gt; \| [CustomBuilder](ts-types.md#custombuilder8) | Yes  | Array of menu item icons and text, or custom component.|
26| options | [MenuOptions](#menuoptions10)                                | No  | Parameters of the context menu.                        |
27
28## bindMenu
29
30bindMenu(isShow: boolean, content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
31
32Menu 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.
33
34**System capability**: SystemCapability.ArkUI.ArkUI.Full
35
36**Parameters**
37
38| Name              | Type                                                        | Mandatory| Description                                                        |
39| -------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
40| isShow<sup>11+</sup> | boolean                                                      | Yes  | Whether to show the menu. The default value is **false**. Menus can be displayed only after all pages are constructed. Therefore, this parameter cannot be set to **true** during page construction. Otherwise, display position and shape errors will occur. Two-way binding is not supported.|
41| content              | Array<[MenuElement](#menuelement)&gt; \| [CustomBuilder](ts-types.md#custombuilder8) | Yes  | Array of menu item icons and text, or custom component.                |
42| options              | [MenuOptions](#menuoptions10)                                | No  | Parameters of the context menu.                                        |
43
44## bindContextMenu<sup>8+</sup>
45
46bindContextMenu(content: CustomBuilder, responseType: ResponseType, options?: ContextMenuOptions)
47
48Context menu bound to the component, which is displayed when the user long-presses or right-clicks the component. Only custom menu items are supported.
49
50**System capability**: SystemCapability.ArkUI.ArkUI.Full
51
52**Parameters**
53
54| Name      | Type                                              | Mandatory| Description                                        |
55| ------------ | -------------------------------------------------- | ---- | -------------------------------------------- |
56| content      | [CustomBuilder](ts-types.md#custombuilder8)        | Yes  | Array of menu item icons and text, or custom component.|
57| responseType | [ResponseType](ts-appendix-enums.md#responsetype8) | Yes  | How the context menu is triggered, which can be long-press or right-click.            |
58| options      | [MenuOptions](#menuoptions10)                      | No  | Parameters of the context menu.                        |
59
60## MenuElement
61
62| Name                 | Type                                  | Mandatory| Description                                                        |
63| --------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
64| value                 | string                                 | Yes  | Menu item text.                                                |
65| icon<sup>10+</sup>    | [ResourceStr](ts-types.md#resourcestr) | No  | Menu item icon.                                                |
66| enabled<sup>11+</sup> | boolean                                | No  | Whether to enable interactions with the menu item.<br>Default value: **true**, indicating that interactions with the menu item are enabled.|
67| action                | () =&gt; void                | Yes  | Action triggered when a menu item is clicked.                                      |
68
69## MenuOptions<sup>10+</sup>
70
71Inherited from [ContextMenuOptions](#contextmenuoptions10).
72
73| Name                         | Type                                        | Mandatory| Description                                                        |
74| ----------------------------- | -------------------------------------------- | ---- | ------------------------------------------------------------ |
75| title                         | string                                       | No  | Menu title.<br>**NOTE**<br>This parameter is effective only when **content** is set to Array<[MenuElement](#menuelement)>.|
76| 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.|
77| 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.|
78| onAppear                      | () =&gt; void                      | No  | Callback triggered when the menu is displayed.                                      |
79| onDisappear                   | () =&gt; void                      | No  | Callback triggered when the menu is hidden.                                      |
80| showInSubWindow<sup>11+</sup> | boolean                                      | No  | Whether to show the menu in a subwindow.                                      |
81
82## ContextMenuOptions<sup>10+</sup>
83
84| Name                 | Type                                                        | Mandatory| Description                                                        |
85| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
86| 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.|
87| 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.|
88| 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.|
89| 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.|
90| preview<sup>11+</sup> | [MenuPreviewMode](ts-appendix-enums.md#menupreviewmode11)\| [CustomBuilder](ts-types.md#custombuilder8) | No  | Preview displayed when the context menu is triggered by a long-press. It can be a screenshot of the target component or custom content.<br>Default value: **MenuPreviewMode.NONE**, indicating no preview.<br>**NOTE**<br>- This parameter is effective only when **responseType** is set to **ResponseType.LongPress**.<br>- If **preview** is set to **MenuPreviewMode.NONE** or is not set, the **enableArrow** parameter is effective.<br>- If **preview** is set to **MenuPreviewMode.IMAGE** or **CustomBuilder**, no arrow will be displayed even when **enableArrow** is **true**.|
91| previewAnimationOptions<sup>11+</sup> | [ContextMenuAnimationOptions](#contextmenuanimationoptions11) | No   | Start scale ratio and end scale ratio (relative to the original preview image) of the preview animation displayed when the component is long pressed<br>Default value: **{scale: [0.95, 1.1]}**<br>**NOTE**<br>- If the value of this parameter is less than or equal to 0, this parameter does not take effect.<br>- This parameter takes effect only when **preview** is set to **MenuPreviewMode.IMAGE.**|
92| onAppear              | () =&gt; void                                      | No  | Callback triggered when the menu is displayed.                                      |
93| onDisappear           | () =&gt; void                                      | No  | Callback triggered when the menu is hidden.                                      |
94| aboutToAppear              | () =&gt; void                                      | No  | Callback triggered when the menu is about to appear.                                      |
95| aboutToDisappear           | () =&gt; void                                      | No  | Callback triggered when the menu is about to disappear.                                      |
96| backgroundColor<sup>11+</sup> | [ResourceColor](ts-types.md#resourcecolor)  | No| Backplane color of the dialog box.<br>Default value: **Color.Transparent**|
97| backgroundBlurStyle<sup>11+</sup> | [BlurStyle](ts-appendix-enums.md#blurstyle9) | No| Background blur style of the dialog box.<br>Default value: **BlurStyle.COMPONENT_ULTRA_THICK**|
98
99## ContextMenuAnimationOptions<sup>11+</sup>
100
101| Name | Type                                      | Mandatory| Description                                |
102| ----- | ------------------------------------------ | ---- | ------------------------------------ |
103| scale | [AnimationRange](#animationrange11)\<number> | No  | Scale ratio of the preview image when the animation starts and scale ratio when the animation ends.|
104
105## AnimationRange<sup>11+</sup>
106
107Describes the scale ratio of the preview image when the animation starts and scale ratio when the animation ends.
108
109**System capability**: SystemCapability.ArkUI.ArkUI.Full
110
111| Value Range        | Description                                                                          |
112| ---------------- | ------------------------------------------------------------------------------ |
113| [from: T, to: T] | **from** indicates the scale ratio of the preview image when the animation starts, and **to** indicates the scale ratio when the animation ends.|
114
115## Example
116
117### Example 1
118
119Menu with Textual Menu Items
120
121```ts
122// xxx.ets
123@Entry
124@Component
125struct MenuExample {
126  build() {
127    Column() {
128      Text('click for Menu')
129    }
130    .width('100%')
131    .margin({ top: 5 })
132    .bindMenu([
133      {
134        value: 'Menu1',
135        action: () => {
136          console.info('handle Menu1 select')
137        }
138      },
139      {
140        value: 'Menu2',
141        action: () => {
142          console.info('handle Menu2 select')
143        }
144      },
145    ])
146  }
147}
148```
149
150![en_image_0000001174582862](figures/en_image_0000001174582862.gif)
151
152### Example 2
153
154Menu with Custom Menu Items
155
156```ts
157@Entry
158@Component
159struct MenuExample {
160  @State listData: number[] = [0, 0, 0]
161
162  @Builder MenuBuilder() {
163    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
164      ForEach(this.listData, (item:number, index) => {
165        Column() {
166          Row() {
167            Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 })
168            Text(`Menu${index as number + 1}`).fontSize(20)
169          }
170          .width('100%')
171          .height(30)
172          .justifyContent(FlexAlign.Center)
173          .align(Alignment.Center)
174          .onClick(() => {
175            console.info(`Menu${index as number + 1} Clicked!`)
176          })
177
178          if (index != this.listData.length - 1) {
179            Divider().height(10).width('80%').color('#ccc')
180          }
181        }.padding(5).height(40)
182      })
183    }.width(100)
184  }
185
186  build() {
187    Column() {
188      Text('click for menu')
189        .fontSize(20)
190        .margin({ top: 20 })
191        .bindMenu(this.MenuBuilder)
192    }
193    .height('100%')
194    .width('100%')
195    .backgroundColor('#f0f0f0')
196  }
197}
198```
199
200![en_image_0000001186807708](figures/en_image_0000001186807708.gif)
201
202### Example 3
203
204Context Menu Displayed Upon Right-Click
205
206```ts
207// xxx.ets
208@Entry
209@Component
210struct ContextMenuExample {
211  @Builder MenuBuilder() {
212    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
213      Text('Test menu item 1')
214        .fontSize(20)
215        .width(100)
216        .height(50)
217        .textAlign(TextAlign.Center)
218      Divider().height(10)
219      Text('Test menu item 2')
220        .fontSize(20)
221        .width(100)
222        .height(50)
223        .textAlign(TextAlign.Center)
224    }.width(100)
225  }
226
227  build() {
228    Column() {
229      Text('rightclick for menu')
230    }
231    .width('100%')
232    .margin({ top: 5 })
233    .bindContextMenu(this.MenuBuilder, ResponseType.RightClick)
234  }
235}
236```
237
238### Example 4
239
240Directive Menu Displayed Upon Right-Click
241
242```ts
243// xxx.ets
244@Entry
245@Component
246struct DirectiveMenuExample {
247  @Builder MenuBuilder() {
248    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
249      Text('Options')
250      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
251      Text('Hide')
252      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
253      Text('Exit')
254    }
255    .width(200)
256  }
257
258  build() {
259    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
260      Column() {
261        Text("DirectiveMenuExample")
262          .fontSize(20)
263          .width('100%')
264          .height("25%")
265          .backgroundColor('#F0F0F0')
266          .textAlign(TextAlign.Center)
267          .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, {
268            enableArrow: true,
269            placement: Placement.Bottom
270          })
271      }
272    }
273    .width('100%')
274    .height('100%')
275  }
276}
277```
278
279![en-us_image_0000001689126950](figures/en-us_image_0000001689126950.png)
280
281### Example 5
282
283Context Menu Displayed Upon Long-Pressing (with Preview of Component Screenshot)
284
285```ts
286// xxx.ets
287@Entry
288@Component
289struct Index {
290  private iconStr: ResourceStr = $r("app.media.icon")
291
292  @Builder
293  MyMenu() {
294    Menu() {
295      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
296      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
297      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
298    }
299  }
300
301  build() {
302    Column({ space: 50 }) {
303      Column() {
304        Column() {
305          Text('preview-image')
306            .width(200)
307            .height(100)
308            .textAlign(TextAlign.Center)
309            .margin(100)
310            .fontSize(30)
311            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
312              { preview: MenuPreviewMode.IMAGE,
313                previewAnimationOptions: {scale: [0.8, 1.0]},
314              })
315            .backgroundColor("#ff3df2f5")
316        }
317      }.width('100%')
318    }
319  }
320}
321```
322
323![preview-image](figures/preview-image.png)
324
325### Example 6
326
327Context Menu Displayed Upon Long-Pressing (with Preview of Custom Content)
328
329```ts
330// xxx.ets
331@Entry
332@Component
333struct Index {
334  private iconStr: ResourceStr = $r("app.media.icon")
335
336  @Builder
337  MyMenu() {
338    Menu() {
339      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
340      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
341      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
342    }
343  }
344
345  @Builder
346  MyPreview() {
347    Column() {
348      Image($r('app.media.icon'))
349        .width(200)
350        .height(200)
351    }
352  }
353
354  build() {
355    Column({ space: 50 }) {
356      Column() {
357        Column() {
358          Text('preview-builder')
359            .width(200)
360            .height(100)
361            .textAlign(TextAlign.Center)
362            .margin(100)
363            .fontSize(30)
364            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
365              {
366                preview: this.MyPreview
367              })
368        }
369      }.width('100%')
370    }
371  }
372}
373```
374
375![preview-builder](figures/preview-builder.png)
376