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>  - Since API version 12, a 500 ms long-press on the menu reveals submenus.
14>
15>  - Since API version 12, the pressed state of the menu follows finger movement.
16>
17>    1. This feature is only available in scenarios where the [Menu](ts-basic-components-menu.md) component is used and the child components include [MenuItem](ts-basic-components-menuitem.md) or [MenuItemGroup](ts-basic-components-menuitemgroup.md).
18>
19>    2. This feature is only available for menus with [MenuPreviewMode](#menupreviewmode11) set to **NONE**.
20
21>    3. The menu animation uses a spring curve. Due to the rebound vibration of the spring curve during the exit, there is a long tail after the menu disappears, which prevents other events from responding.
22
23
24## bindMenu
25
26bindMenu(content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
27
28Binds a menu to this 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.
29
30**Atomic service API**: This API can be used in atomic services since API version 11.
31
32**System capability**: SystemCapability.ArkUI.ArkUI.Full
33
34**Parameters**
35
36| Name | Type                                                        | Mandatory| Description                                        |
37| ------- | ------------------------------------------------------------ | ---- | -------------------------------------------- |
38| content | Array<[MenuElement](#menuelement)&gt; \| [CustomBuilder](ts-types.md#custombuilder8) | Yes  | Array of menu item icons and text, or custom component.|
39| options | [MenuOptions](#menuoptions10)                                | No  | Parameters of the context menu.                        |
40
41## bindMenu<sup>11+</sup>
42
43bindMenu(isShow: boolean, content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
44
45Binds a menu to this 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.
46
47**Atomic service API**: This API can be used in atomic services since API version 12.
48
49**System capability**: SystemCapability.ArkUI.ArkUI.Full
50
51**Parameters**
52
53| Name              | Type                                                        | Mandatory| Description                                                        |
54| -------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
55| 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.|
56| content              | Array<[MenuElement](#menuelement)&gt; \| [CustomBuilder](ts-types.md#custombuilder8) | Yes  | Array of menu item icons and text, or custom component.                |
57| options              | [MenuOptions](#menuoptions10)                                | No  | Parameters of the context menu.                                        |
58
59## bindContextMenu<sup>8+</sup>
60
61bindContextMenu(content: CustomBuilder, responseType: ResponseType, options?: ContextMenuOptions)
62
63Binds a context menu to this component, which is displayed when the user long-presses or right-clicks the component. Only custom menu items are supported.
64
65**Atomic service API**: This API can be used in atomic services since API version 11.
66
67**System capability**: SystemCapability.ArkUI.ArkUI.Full
68
69**Parameters**
70
71| Name      | Type                                              | Mandatory| Description                            |
72| ------------ | -------------------------------------------------- | ---- | -------------------------------- |
73| content      | [CustomBuilder](ts-types.md#custombuilder8)        | Yes  | Builder of the custom menu content.          |
74| responseType | [ResponseType](ts-appendix-enums.md#responsetype8) | Yes  | How the context menu is triggered, which can be long-press or right-click. Long pressing with a mouse device is not supported.|
75| options      | [ContextMenuOptions](#contextmenuoptions10)        | No  | Parameters of the context menu.            |
76
77## bindContextMenu<sup>12+</sup>
78
79bindContextMenu(isShown: boolean, content: CustomBuilder, options?: ContextMenuOptions)
80
81Binds a context menu to the component, whose visibility is subject to the **isShown** settings.
82
83If **isShown** is **true**, the menu is displayed. If **isShown** is set to **false**, the menu is hidden. The menu items need to be customized.
84
85The position of the context menu is subject to the **placement** settings, rather than where the component is clicked.
86
87
88**System capability**: SystemCapability.ArkUI.ArkUI.Full
89
90**Atomic service API**: This API can be used in atomic services since API version 11.
91
92**Parameters**
93
94| Name      | Type                                              | Mandatory| Description                                        |
95| ------------ | -------------------------------------------------- | ---- | -------------------------------------------- |
96| isShown | boolean | Yes  | Whether to show the context menu. The value **true** means to show the context menu, and **false** (default) means the opposite. The menu can be displayed properly only when the related page has been built. If this parameter is set to **true** before the build is complete, display issues, such as misplacement, distortion, or failure to pop up, may occur. Currently, two-way data binding is not supported, and dragging cannot be triggered by long press.            |
97| content      | [CustomBuilder](ts-types.md#custombuilder8)        | Yes  | Builder of the custom menu content.|
98| options      | [ContextMenuOptions](#contextmenuoptions10)                      | No  | Parameters of the context menu.                        |
99
100## MenuElement
101
102| Name                 | Type                                  | Mandatory| Description                                                        |
103| --------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
104| value                 | [ResourceStr](ts-types.md#resourcestr) | Yes  | Menu item text.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                                                |
105| icon<sup>10+</sup>    | [ResourceStr](ts-types.md#resourcestr) | No  | Menu item icon.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                                                |
106| 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.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
107| action                | () =&gt; void                | Yes  | Action triggered when a menu item is clicked.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                                      |
108| symbolIcon<sup>12+</sup>                | [SymbolGlyphModifier](ts-universal-attributes-attribute-modifier.md)                | No  | Icon of a menu item. When this parameter is set, the original icon is not displayed.<br>**Atomic service API**: This API can be used in atomic services since API version 12.                                      |
109
110## MenuOptions<sup>10+</sup>
111
112Inherits from [ContextMenuOptions](#contextmenuoptions10).
113
114| Name                         | Type                                  | Mandatory| Description                                                        |
115| ----------------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
116| title                         | [ResourceStr](ts-types.md#resourcestr) | No  | Menu title.<br>**NOTE**<br>This parameter is effective only when **content** is set to Array<[MenuElement](#menuelement)>.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
117| showInSubWindow<sup>11+</sup> | boolean                                | No  | Whether to show the menu in a subwindow.<br>Default value: **true** for 2-in-1 devices and **false** for other devices<br>**Atomic service API**: This API can be used in atomic services since API version 12.                    |
118
119## ContextMenuOptions<sup>10+</sup>
120
121| Name                 | Type                                                        | Mandatory| Description                                                        |
122| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
123| offset                | [Position](ts-types.md#position)                            | 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.Right**, 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.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
124| 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. In this case, if [bindContextMenu<sup>8+</sup>](#bindcontextmenu8) is used, the menu is displayed at the clicked position; if [bindContextMenu<sup>12+</sup>](#bindcontextmenu12) is used, the default value **Placement.BottomLeft** is used.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
125| 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. This API is supported in **bindContextMenu** since API version 10 and **bindMenu** since API version 12.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
126| arrowOffset           | [Length](ts-types.md#length)                                 | No  | Offset of the arrow relative to the context menu. 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.<br>**NOTE**<br>The safe distance of the arrow from the four sides of the menu is the sum of the menu's corner radius and half the width of the arrow.<br>The value of **placement** determines whether the offset is horizontal or vertical.<br>When the arrow is in the horizontal direction of the menu, the offset is the distance from the arrow to the leftmost arrow's safe distance. When the arrow is in the vertical direction of the menu, the offset is the distance from the arrow to the topmost arrow's safe distance.<br>The default position where the arrow is displayed varies with the value of **placement**:<br>Without any avoidance by the menu, when **placement** is set to **Placement.Top** or **Placement.Bottom**, the arrow is displayed horizontally and is centered by default;<br>when **placement** is set to **Placement.Left** or **Placement.Right**, the arrow is displayed vertically and is centered by default;<br>when **placement** is set to **Placement.TopLeft** or **Placement.BottomLeft**, the arrow is displayed horizontally by default, and the distance from the arrow to the left edge of the menu is the arrow's safe distance;<br>when **placement** is set to **Placement.TopRight** or **Placement.BottomRight**, the arrow is displayed horizontally by default, and the distance from the arrow to the right edge of the menu is the arrow's safe distance;<br>when **placement** is set to **Placement.LeftTop** or **Placement.RightTop**, the arrow is displayed vertically by default, and the distance from the arrow to the top edge of the menu is the arrow's safe distance;<br>when **placement** is set to **Placement.LeftBottom** or **Placement.RightBottom**, the arrow is displayed vertically by default, and the distance from the arrow to the bottom edge of the menu is the arrow's safe distance.<br>  This API is supported in **bindContextMenu** since API version 10 and **bindMenu** since API version 12.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
127| preview<sup>11+</sup> | [MenuPreviewMode](#menupreviewmode11)\| [CustomBuilder](ts-types.md#custombuilder8) | No  | Preview displayed when the context menu is triggered by a long-press or by calling [bindContextMenu<sup>12+</sup>](#bindcontextmenu12). 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 has no effect when **responseType** is set to **ResponseType.RightClick**.<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**.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
128| 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 is less than or equal to 0, this parameter does not take effect.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
129| onAppear              | () =&gt; void                                      | No  | Callback triggered when the menu is displayed.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                                      |
130| onDisappear           | () =&gt; void                                      | No  | Callback triggered when the menu is hidden.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                                      |
131| aboutToAppear              | () =&gt; void                                      | No  | Callback triggered when the menu is about to appear.<br>**Atomic service API**: This API can be used in atomic services since API version 12.                                      |
132| aboutToDisappear           | () =&gt; void                                      | No  | Callback triggered when the menu is about to disappear.<br>**Atomic service API**: This API can be used in atomic services since API version 12.                                      |
133| backgroundColor<sup>11+</sup> | [ResourceColor](ts-types.md#resourcecolor)  | No| Backplane color of the dialog box.<br>Default value: **Color.Transparent**<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
134| backgroundBlurStyle<sup>11+</sup> | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | No| Background blur style of the dialog box.<br>Default value: **BlurStyle.COMPONENT_ULTRA_THICK**<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
135| transition<sup>12+</sup> | [TransitionEffect](ts-transition-animation-component.md#transitioneffect10)| No  | Transition effect for the entrance and exit of the menu.<br>**NOTE**<br>During the exit animation of the menu, if there is a switch between landscape and portrait modes, the menu will make way. Level-2 menus do not inherit custom animations. The level-2 menu can be clicked during the pop-up process, but not during the execution of the exit animation.<br>For details, see [TransitionEffect](ts-transition-animation-component.md#transitioneffect10).<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
136| borderRadius<sup>12+</sup>  | [Length](ts-types.md#length) \| [BorderRadiuses](ts-types.md#borderradiuses9) \| [LocalizedBorderRadiuses](ts-types.md#localizedborderradiuses12) | No  | Border radius of the menu.<br>**NOTE**<br> The value cannot be in percentage.<br>If the sum of the two maximum corner radii in the horizontal direction exceeds the menu's width, or if the sum of the two maximum corner radii in the vertical direction exceeds the menu's height, the default corner radius of the menu will be used.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
137
138## MenuPreviewMode<sup>11+</sup>
139
140**Atomic service API**: This API can be used in atomic services since API version 12.
141
142**System capability**: SystemCapability.ArkUI.ArkUI.Full
143
144| Name | Description                                  |
145| ----- | -------------------------------------- |
146| NONE  | No preview is displayed.                      |
147| IMAGE | The preview is a screenshot of the component on which a long-press triggers the context menu.|
148
149## ContextMenuAnimationOptions<sup>11+</sup>
150
151**Atomic service API**: This API can be used in atomic services since API version 12.
152
153| Name | Type                                      | Mandatory| Description                                |
154| ----- | ------------------------------------------ | ---- | ------------------------------------ |
155| scale | [AnimationRange](#animationrange11)\<number> | No  | Scale ratio of the preview image when the animation starts and scale ratio when the animation ends.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
156| transition<sup>12+</sup> | [TransitionEffect](ts-transition-animation-component.md#transitioneffect10)| No  | Transition effect for the entrance and exit of the menu.<br>**NOTE**<br>During the exit animation of the menu, if there is a switch between landscape and portrait modes, the menu will make way. Level-2 menus do not inherit custom animations. The level-2 menu can be clicked during the pop-up process, but not during the execution of the exit animation.<br>For details, see [TransitionEffect](ts-transition-animation-component.md#transitioneffect10).|
157| hoverScale<sup>12+</sup> | [AnimationRange](#animationrange11)\<number> | No  | Sets the scale ratio of the original component snapshot to the preview image at the beginning and end of the scale animation in a custom long press scenario. There is a transition animation for the switch with the preview image.<br>**NOTE**<br> If the value is less than or equal to 0, this API does not take effect.<br>This API does not take effect in [bindContextMenu<sup>12+</sup>](#bindcontextmenu12) scenarios.<br> This API does not take effect when **transition** is set.<br> If this API and the **scale** API are used at the same time, the start value of the **scale** API does not take effect.<br> To ensure the optimal experience, it is not recommended that the final preview image size be smaller than the size of the original component snapshot. The width and height of the preview animation are affected by the component snapshot and the custom preview size. Verify the display effect based on the actual use case.|
158
159## AnimationRange<sup>11+</sup>
160
161Describes the scale ratio relative to the preview image at the beginning and end of the scale animation.
162
163**System capability**: SystemCapability.ArkUI.ArkUI.Full
164
165**Atomic service API**: This API can be used in atomic services since API version 12.
166
167| Value Range        | Description                                                                          |
168| ---------------- | ------------------------------------------------------------------------------ |
169| [from: T, to: T] | **from** indicates the scale ratio at the beginning of the animation, and **to** indicates the scale ratio at the end of the animation.|
170
171## Example
172
173### Example 1
174
175Menu with textual menu items:
176
177```ts
178// xxx.ets
179@Entry
180@Component
181struct MenuExample {
182  build() {
183    Column() {
184      Text('click for Menu')
185        .bindMenu([
186          {
187            value: 'Menu1',
188            action: () => {
189              console.info('handle Menu1 select')
190            }
191          },
192          {
193            value: 'Menu2',
194            action: () => {
195              console.info('handle Menu2 select')
196            }
197          },
198        ])
199    }
200    .width('100%')
201    .margin({ top: 5 })
202  }
203}
204```
205
206![en_image_0000001174582862](figures/en_image_0000001174582862.gif)
207
208### Example 2
209
210Menu with custom menu items:
211
212```ts
213@Entry
214@Component
215struct MenuExample {
216  @State listData: number[] = [0, 0, 0]
217
218  @Builder MenuBuilder() {
219    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
220      ForEach(this.listData, (item:number, index) => {
221        Column() {
222          Row() {
223            Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 })
224            Text(`Menu${index as number + 1}`).fontSize(20)
225          }
226          .width('100%')
227          .height(30)
228          .justifyContent(FlexAlign.Center)
229          .align(Alignment.Center)
230          .onClick(() => {
231            console.info(`Menu${index as number + 1} Clicked!`)
232          })
233
234          if (index != this.listData.length - 1) {
235            Divider().height(10).width('80%').color('#ccc')
236          }
237        }.padding(5).height(40)
238      })
239    }.width(100)
240  }
241
242  build() {
243    Column() {
244      Text('click for menu')
245        .fontSize(20)
246        .margin({ top: 20 })
247        .bindMenu(this.MenuBuilder)
248    }
249    .height('100%')
250    .width('100%')
251    .backgroundColor('#f0f0f0')
252  }
253}
254```
255
256![en_image_0000001186807708](figures/en_image_0000001186807708.gif)
257
258### Example 3
259
260Context menu displayed upon long-press:
261
262```ts
263// xxx.ets
264@Entry
265@Component
266struct ContextMenuExample {
267  @Builder MenuBuilder() {
268    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
269      Text('Test menu item 1')
270        .fontSize(20)
271        .width(100)
272        .height(50)
273        .textAlign(TextAlign.Center)
274      Divider().height(10)
275      Text('Test menu item 2')
276        .fontSize(20)
277        .width(100)
278        .height(50)
279        .textAlign(TextAlign.Center)
280    }.width(100)
281  }
282
283  build() {
284    Column() {
285      Text('LongPress for menu')
286    }
287    .width('100%')
288    .margin({ top: 5 })
289    .bindContextMenu(this.MenuBuilder, ResponseType.LongPress)
290  }
291}
292```
293
294![longMenu](figures/longMenu.gif)
295
296### Example 4
297
298Directive menu displayed upon right-click:
299
300```ts
301// xxx.ets
302@Entry
303@Component
304struct DirectiveMenuExample {
305  @Builder MenuBuilder() {
306    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
307      Text('Options')
308      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
309      Text('Hide')
310      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
311      Text('Exit')
312    }
313    .width(200)
314  }
315
316  build() {
317    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
318      Column() {
319        Text("DirectiveMenuExample")
320          .fontSize(20)
321          .width('100%')
322          .height("25%")
323          .backgroundColor('#F0F0F0')
324          .textAlign(TextAlign.Center)
325          .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, {
326            enableArrow: true,
327            placement: Placement.Bottom
328          })
329      }
330    }
331    .width('100%')
332    .height('100%')
333  }
334}
335```
336
337![en-us_image_0000001689126950](figures/en-us_image_0000001689126950.png)
338
339### Example 5
340
341Context menu displayed upon long-pressing (with preview of component screenshot):
342
343```ts
344// xxx.ets
345@Entry
346@Component
347struct Index {
348  private iconStr: ResourceStr = $r("app.media.icon")
349
350  @Builder
351  MyMenu() {
352    Menu() {
353      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
354      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
355      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
356    }
357  }
358
359  build() {
360    Column({ space: 50 }) {
361      Column() {
362        Column() {
363          Text('preview-image')
364            .width(200)
365            .height(100)
366            .textAlign(TextAlign.Center)
367            .margin(100)
368            .fontSize(30)
369            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
370              { preview: MenuPreviewMode.IMAGE,
371                previewAnimationOptions: {scale: [0.8, 1.0]},
372              })
373            .backgroundColor("#ff3df2f5")
374        }
375      }.width('100%')
376    }
377  }
378}
379```
380
381![preview-image](figures/preview-image.png)
382
383### Example 6
384
385Context menu displayed upon long-pressing (with preview of custom content):
386
387```ts
388// xxx.ets
389@Entry
390@Component
391struct Index {
392  private iconStr: ResourceStr = $r("app.media.icon")
393
394  @Builder
395  MyMenu() {
396    Menu() {
397      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
398      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
399      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
400    }
401  }
402
403  @Builder
404  MyPreview() {
405    Column() {
406      Image($r('app.media.icon'))
407        .width(200)
408        .height(200)
409    }
410  }
411
412  build() {
413    Column({ space: 50 }) {
414      Column() {
415        Column() {
416          Text('preview-builder')
417            .width(200)
418            .height(100)
419            .textAlign(TextAlign.Center)
420            .margin(100)
421            .fontSize(30)
422            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
423              {
424                preview: this.MyPreview
425              })
426        }
427      }.width('100%')
428    }
429  }
430}
431```
432
433![preview-builder](figures/preview-builder.png)
434
435### Example 7
436
437Context menu displayed upon setting isShown (with preview of custom content):
438
439```ts
440// xxx.ets
441@Entry
442@Component
443struct Index {
444  private iconStr: ResourceStr = $r("app.media.icon")
445  @State isShown: boolean = false
446
447  @Builder
448  MyMenu() {
449    Menu() {
450      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
451      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
452      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
453    }
454  }
455
456  @Builder
457  MyPreview() {
458    Column() {
459      Image($r('app.media.icon'))
460        .width(200)
461        .height(200)
462    }
463  }
464
465  build() {
466    Column({ space: 50 }) {
467      Column() {
468        Column() {
469          Text('preview-builder')
470            .width(200)
471            .height(100)
472            .textAlign(TextAlign.Center)
473            .margin(100)
474            .fontSize(30)
475            .bindContextMenu(this.isShown, this.MyMenu,
476              {
477                preview: this.MyPreview,
478                onDisappear: ()=>{
479                    this.isShown = false;
480                }
481              })
482          Button('click')
483            .onClick(()=>{
484                this.isShown = true;
485             })
486        }
487      }.width('100%')
488    }
489  }
490}
491```
492
493### Example 8
494
495This example customizes the display and exit animation effects of the menu and preview through the **transition** attribute.
496
497```ts
498// xxx.ets
499@Entry
500@Component
501struct MenuExample {
502  @Builder MenuBuilder() {
503    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
504      Text('Test menu item 1')
505        .fontSize(12)
506        .width(200)
507        .height(30)
508        .textAlign(TextAlign.Center)
509      Divider().height(10)
510      Text('Test menu item 2')
511        .fontSize(12)
512        .width(100)
513        .height(30)
514        .textAlign(TextAlign.Center)
515    }.width(100)
516  }
517  @Builder
518  MyPreview() {
519    Column() {
520      Image($r('app.media.icon'))
521        .width(50)
522        .height(50)
523    }
524  }
525  @State isShow:boolean = false
526  private iconStr: ResourceStr = $r("app.media.icon")
527
528  @Builder
529  MyMenu() {
530    Menu() {
531      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
532      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
533      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
534    }
535  }
536  build() {
537    Column() {
538      Button('LongPress bindContextMenu')
539        .margin({ top: 15 })
540        .bindContextMenu(
541          this.MenuBuilder,
542          ResponseType.LongPress,{
543          transition: TransitionEffect.OPACITY.animation({ duration: 4000, curve: Curve.Ease }).combine(
544            TransitionEffect.rotate({ z: 1, angle: 180 })),
545          preview: this.MyPreview,
546          previewAnimationOptions: {
547            scale: [0.8, 1.0],
548            transition: TransitionEffect.OPACITY.animation({ duration: 4000, curve: Curve.Ease }).combine(
549              TransitionEffect.rotate({ z: 1, angle: 180 }))
550          }
551        })
552    }
553    .width('100%')
554    .margin({ top: 5 })
555  }
556}
557```
558
559![preview-builder](figures/menu2.gif)
560
561### Example 9
562
563This example demonstrates a regular menu (using symbol-type icons).
564
565```ts
566// xxx.ets
567import { SymbolGlyphModifier } from '@kit.ArkUI';
568@Entry
569@Component
570struct MenuExample {
571  @State symbolIconModifier1: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.ohos_photo')).fontSize('24vp');
572  @State symbolIconModifier2: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.ohos_photo')).fontSize('24vp');
573  build() {
574    Column() {
575      Text('click for Menu')
576    }
577    .width('100%')
578    .margin({ top: 5 })
579    .bindMenu([
580      {
581        value: 'Menu1',
582        symbolIcon:this.symbolIconModifier1,
583        action: () => {
584          console.info('handle Menu1 select')
585        }
586      },
587      {
588        value: 'Menu2',
589        symbolIcon:this.symbolIconModifier2,
590        action: () => {
591          console.info('handle Menu2 select')
592        }
593      },
594    ])
595  }
596}
597```
598
599![zh-cn_image_0000001174582862](figures/preview-symbol.jpeg)
600
601### Example 10
602
603This example uses **hoverScale** to implement the transition from the component snapshot to the custom preview image.
604
605```ts
606// xxx.ets
607@Entry
608@Component
609struct Index {
610  private iconStr: ResourceStr = $r("app.media.app_icon")
611
612  @Builder
613  MyMenu() {
614    Menu() {
615      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
616      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
617      MenuItem({ startIcon: this.iconStr, content: "Menu option" })
618    }
619  }
620
621  @Builder
622  MyPreview() {
623    Column() {
624      Image($r('app.media.example'))
625        .width(200)
626        .height(200)
627    }
628  }
629
630  build() {
631    Column({ space: 50 }) {
632      Column() {
633        Column() {
634          Image($r('app.media.example'))
635            .width(100)
636            .height(100)
637            .margin(100)
638            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
639              {
640                preview: this.MyPreview,
641                previewAnimationOptions: {
642                  hoverScale: [1.0, 0.95]
643                }
644              })
645        }
646      }.width('100%')
647    }
648  }
649}
650```
651
652![preview-builder](figures/hoverScale.gif)
653