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> - When the window size changes, the menu is automatically hidden. 14> 15> - The menu animation uses a spring curve. Due to the rebound and oscillation of the spring curve during the exit of the animation, there is a prolonged tail effect, which prevents the menu from responding to other events after it disappears. 16> 17> - If a component is a draggable node and **bindContextMenu** is used without a preview specified, the menu will display a floating drag preview, and the menu options will not avoid the preview. To address this issue, you can set a preview or configure the target node to be non-draggable, based on the use case. 18> 19> - Since API version 12, menus allow users to display a submenu with a 500 ms long press, with the pressed state following the movement of the finger. 20> 21> 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). 22> 23> 2. This feature is only available for menus with [MenuPreviewMode](#menupreviewmode11) set to **NONE**. 24 25 26## bindMenu 27 28bindMenu(content: Array<MenuElement> | CustomBuilder, options?: MenuOptions) 29 30Binds 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. 31 32**Atomic service API**: This API can be used in atomic services since API version 11. 33 34**System capability**: SystemCapability.ArkUI.ArkUI.Full 35 36**Parameters** 37 38| Name | Type | Mandatory| Description | 39| ------- | ------------------------------------------------------------ | ---- | -------------------------------------------- | 40| content | Array<[MenuElement](#menuelement)> \| [CustomBuilder](ts-types.md#custombuilder8) | Yes | Array of menu item icons and text, or custom component.| 41| options | [MenuOptions](#menuoptions10) | No | Parameters of the context menu. | 42 43## bindMenu<sup>11+</sup> 44 45bindMenu(isShow: boolean, content: Array<MenuElement> | CustomBuilder, options?: MenuOptions) 46 47Binds 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. 48 49**Atomic service API**: This API can be used in atomic services since API version 12. 50 51**System capability**: SystemCapability.ArkUI.ArkUI.Full 52 53**Parameters** 54 55| Name | Type | Mandatory| Description | 56| -------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 57| isShow<sup>11+</sup> | boolean | Yes | Whether to show the menu. The default value is **false**. The menu can be displayed only after the entire page is fully constructed. Therefore, to avoid incorrect display positions and shapes, do not set this parameter to **true** while the page is still being constructed.| 58| content | Array<[MenuElement](#menuelement)> \| [CustomBuilder](ts-types.md#custombuilder8) | Yes | Array of menu item icons and text, or custom component. | 59| options | [MenuOptions](#menuoptions10) | No | Parameters of the context menu. | 60 61## bindContextMenu<sup>8+</sup> 62 63bindContextMenu(content: CustomBuilder, responseType: ResponseType, options?: ContextMenuOptions) 64 65Binds 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. 66 67**Atomic service API**: This API can be used in atomic services since API version 11. 68 69**System capability**: SystemCapability.ArkUI.ArkUI.Full 70 71**Parameters** 72 73| Name | Type | Mandatory| Description | 74| ------------ | -------------------------------------------------- | ---- | -------------------------------- | 75| content | [CustomBuilder](ts-types.md#custombuilder8) | Yes | Builder of the custom menu content. | 76| 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.| 77| options | [ContextMenuOptions](#contextmenuoptions10) | No | Parameters of the context menu. | 78 79## bindContextMenu<sup>12+</sup> 80 81bindContextMenu(isShown: boolean, content: CustomBuilder, options?: ContextMenuOptions) 82 83Binds a context menu to the component, whose visibility is subject to the **isShown** settings. 84 85If **isShown** is **true**, the menu is displayed. If **isShown** is set to **false**, the menu is hidden. The menu items need to be customized. 86 87The position of the context menu is subject to the **placement** settings, rather than where the component is clicked. 88 89 90**System capability**: SystemCapability.ArkUI.ArkUI.Full 91 92**Atomic service API**: This API can be used in atomic services since API version 11. 93 94**Parameters** 95 96| Name | Type | Mandatory| Description | 97| ------------ | -------------------------------------------------- | ---- | -------------------------------------------- | 98| 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 constructed. If this parameter is set to **true** before the construction is complete, display issues, such as misplacement, distortion, or failure to pop up, may occur. To trigger dragging by long presses is not supported. This parameter supports two-way binding through the [!! syntax](../../../quick-start/arkts-new-binding.md).| 99| content | [CustomBuilder](ts-types.md#custombuilder8) | Yes | Builder of the custom menu content.| 100| options | [ContextMenuOptions](#contextmenuoptions10) | No | Parameters of the context menu. | 101 102## MenuElement 103 104| Name | Type | Mandatory| Description | 105| --------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ | 106| 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. | 107| 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. | 108| 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.| 109| action | () => 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. | 110| 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. | 111 112## MenuOptions<sup>10+</sup> 113 114Inherits from [ContextMenuOptions](#contextmenuoptions10). 115 116| Name | Type | Mandatory| Description | 117| ----------------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ | 118| 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.| 119| 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. | 120 121## ContextMenuOptions<sup>10+</sup> 122 123| Name | Type | Mandatory| Description | 124| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 125| 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>Default value: **{x:0, y:0}**<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.| 126| 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 [bindMenu](#bindmenu11) is used, the default value of **placement** is **Placement.BottomLeft**; if [bindContextMenu<sup>8+</sup>](#bindcontextmenu8) is used, the menu is displayed at the touched position; if [bindContextMenu<sup>12+</sup>](#bindcontextmenu12) is used, the default value is **Placement.BottomLeft**.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 127| 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.| 128| 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>Default value: **0**<br>Unit: vp<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.| 129| 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.| 130| 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], transition: undefined, hoverScale: undefined }**<br>**NOTE**<br>If the value is less than or equal to 0, this API does not take effect.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 131| onAppear | () => 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. | 132| onDisappear | () => 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. | 133| aboutToAppear | () => 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. | 134| aboutToDisappear | () => 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. | 135| 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.| 136| 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.| 137| 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.| 138| 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>Default value: **8vp** for 2-in-1 devices and **20vp** for other devices<br>**NOTE**<br> The value can 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.| 139| layoutRegionMargin<sup>13+</sup> | [Margin](ts-types.md#margin) | No | Minimum margin between the preview and menu layout for top, bottom, left, and right edges.<br>**NOTE**<br> Only vp, px, fp, lpx, and percentage units are supported.<br> Any abnormal or negative values will be treated as the default values.<br> If **preview** is set to **CustomBuilder**, setting **margin.left** or **margin.right** will remove the maximum grid width restriction for the preview.<br> Be cautious not to set excessively large margins that are too large, which could reduce the layout area and affect the proper layout of the preview and menu.<br>If the sum of horizontal margins exceeds the maximum layout width, **margin.left** and **margin.right** will be ignored and default values will be applied.<br> If the sum of vertical margins exceeds the maximum layout width, **margin.top** and **margin.bottom** will be ignored and default values will be applied.<br>**Atomic service API**: This API can be used in atomic services since API version 13.| 140 141## MenuPreviewMode<sup>11+</sup> 142 143**Atomic service API**: This API can be used in atomic services since API version 12. 144 145**System capability**: SystemCapability.ArkUI.ArkUI.Full 146 147| Name | Description | 148| ----- | -------------------------------------- | 149| NONE | No preview is displayed. | 150| IMAGE | The preview is a screenshot of the component on which a long-press triggers the context menu.| 151 152## ContextMenuAnimationOptions<sup>11+</sup> 153 154**Atomic service API**: This API can be used in atomic services since API version 12. 155 156| Name | Type | Mandatory| Description | 157| ----- | ------------------------------------------ | ---- | ------------------------------------ | 158| scale | [AnimationRange](#animationrange11)\<number> | No | Relative scale ratio at the start and end of the animation compared to the original preview image.<br>**NOTE**<br>The scale ratio must be set based on the specific use case. It is recommended that it be less than the width of the preview image or the maximum constraint of the layout.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 159| 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).| 160| 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.| 161 162## AnimationRange<sup>11+</sup> 163 164Describes the scale ratio relative to the preview image at the beginning and end of the scale animation. 165 166**System capability**: SystemCapability.ArkUI.ArkUI.Full 167 168**Atomic service API**: This API can be used in atomic services since API version 12. 169 170| Value Range | Description | 171| ---------------- | ------------------------------------------------------------------------------ | 172| [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.| 173 174## Example 175 176### Example 1: Displaying a Basic Menu 177 178This example demonstrates how to use **bindMenu** to display a basic menu using **MenuElement**. 179 180```ts 181// xxx.ets 182@Entry 183@Component 184struct MenuExample { 185 build() { 186 Column() { 187 Text('click for Menu') 188 .bindMenu([ 189 { 190 value: 'Menu1', 191 action: () => { 192 console.info('handle Menu1 select') 193 } 194 }, 195 { 196 value: 'Menu2', 197 action: () => { 198 console.info('handle Menu2 select') 199 } 200 }, 201 ]) 202 } 203 .width('100%') 204 .margin({ top: 5 }) 205 } 206} 207``` 208 209 210 211### Example 2: Displaying a Custom Menu 212 213This example shows how to use **bindMenu** with a custom builder to create a custom menu. 214 215```ts 216@Entry 217@Component 218struct MenuExample { 219 @State listData: number[] = [0, 0, 0] 220 221 @Builder MenuBuilder() { 222 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 223 ForEach(this.listData, (item:number, index) => { 224 Column() { 225 Row() { 226 Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 }) 227 Text(`Menu${index as number + 1}`).fontSize(20) 228 } 229 .width('100%') 230 .height(30) 231 .justifyContent(FlexAlign.Center) 232 .align(Alignment.Center) 233 .onClick(() => { 234 console.info(`Menu${index as number + 1} Clicked!`) 235 }) 236 237 if (index != this.listData.length - 1) { 238 Divider().height(10).width('80%').color('#ccc') 239 } 240 }.padding(5).height(40) 241 }) 242 }.width(100) 243 } 244 245 build() { 246 Column() { 247 Text('click for menu') 248 .fontSize(20) 249 .margin({ top: 20 }) 250 .bindMenu(this.MenuBuilder) 251 } 252 .height('100%') 253 .width('100%') 254 .backgroundColor('#f0f0f0') 255 } 256} 257``` 258 259 260 261### Example 3: Displaying a Menu on Long Press 262 263This example demonstrates how to use **bindContextMenu** with **ResponseType.LongPress** to display a menu on long press. 264 265```ts 266// xxx.ets 267@Entry 268@Component 269struct ContextMenuExample { 270 @Builder MenuBuilder() { 271 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 272 Text('Test menu item 1') 273 .fontSize(20) 274 .width(100) 275 .height(50) 276 .textAlign(TextAlign.Center) 277 Divider().height(10) 278 Text('Test menu item 2') 279 .fontSize(20) 280 .width(100) 281 .height(50) 282 .textAlign(TextAlign.Center) 283 }.width(100) 284 } 285 286 build() { 287 Column() { 288 Text('LongPress for menu') 289 } 290 .width('100%') 291 .margin({ top: 5 }) 292 .bindContextMenu(this.MenuBuilder, ResponseType.LongPress) 293 } 294} 295``` 296 297 298 299### Example 4: Displaying a Menu with an Arrow on Right-Clicking 300 301This example shows how to use **bindContextMenu** with **ResponseType.RightClick** and **enableArrow** to display a menu with an arrow on right-clicking. 302 303```ts 304// xxx.ets 305@Entry 306@Component 307struct DirectiveMenuExample { 308 @Builder MenuBuilder() { 309 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 310 Text('Options') 311 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 312 Text('Hide') 313 Divider().strokeWidth(2).margin(5).color('#F0F0F0') 314 Text('Exit') 315 } 316 .width(200) 317 } 318 319 build() { 320 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 321 Column() { 322 Text("DirectiveMenuExample") 323 .fontSize(20) 324 .width('100%') 325 .height("25%") 326 .backgroundColor('#F0F0F0') 327 .textAlign(TextAlign.Center) 328 .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, { 329 enableArrow: true, 330 placement: Placement.Bottom 331 }) 332 } 333 } 334 .width('100%') 335 .height('100%') 336 } 337} 338``` 339 340 341 342### Example 5: Displaying a Menu with a Screenshot Preview on Long Press 343 344This example demonstrates how to use **bindContextMenu** with **ResponseType.LongPress** and **MenuPreviewMode.IMAGE** to display a menu with a screenshot preview on long pressure. 345 346```ts 347// xxx.ets 348@Entry 349@Component 350struct Index { 351 private iconStr: ResourceStr = $r("app.media.icon") 352 353 @Builder 354 MyMenu() { 355 Menu() { 356 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 357 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 358 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 359 } 360 } 361 362 build() { 363 Column({ space: 50 }) { 364 Column() { 365 Column() { 366 Text('preview-image') 367 .width(200) 368 .height(100) 369 .textAlign(TextAlign.Center) 370 .margin(100) 371 .fontSize(30) 372 .bindContextMenu(this.MyMenu, ResponseType.LongPress, 373 { preview: MenuPreviewMode.IMAGE, 374 previewAnimationOptions: {scale: [0.8, 1.0]}, 375 }) 376 .backgroundColor("#ff3df2f5") 377 } 378 }.width('100%') 379 } 380 } 381} 382``` 383 384 385 386### Example 6: Displaying a Menu with a Custom Preview on Long Press 387 388This example shows how to use **bindContextMenu** with **ResponseType.LongPress** and a custom preview builder to display a menu with a custom preview on long pressure. 389 390```ts 391// xxx.ets 392@Entry 393@Component 394struct Index { 395 private iconStr: ResourceStr = $r("app.media.icon") 396 397 @Builder 398 MyMenu() { 399 Menu() { 400 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 401 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 402 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 403 } 404 } 405 406 @Builder 407 MyPreview() { 408 Column() { 409 Image($r('app.media.icon')) 410 .width(200) 411 .height(200) 412 } 413 } 414 415 build() { 416 Column({ space: 50 }) { 417 Column() { 418 Column() { 419 Text('preview-builder') 420 .width(200) 421 .height(100) 422 .textAlign(TextAlign.Center) 423 .margin(100) 424 .fontSize(30) 425 .bindContextMenu(this.MyMenu, ResponseType.LongPress, 426 { 427 preview: this.MyPreview 428 }) 429 } 430 }.width('100%') 431 } 432 } 433} 434``` 435 436 437 438### Example 7: Using a State Variable for Menu Visibility 439 440This example demonstrates how to use **bindContextMenu** with a state variable to control the visibility of the menu. 441 442```ts 443// xxx.ets 444@Entry 445@Component 446struct Index { 447 private iconStr: ResourceStr = $r("app.media.icon") 448 @State isShown: boolean = false 449 450 @Builder 451 MyMenu() { 452 Menu() { 453 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 454 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 455 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 456 } 457 } 458 459 @Builder 460 MyPreview() { 461 Column() { 462 Image($r('app.media.icon')) 463 .width(200) 464 .height(200) 465 } 466 } 467 468 build() { 469 Column({ space: 50 }) { 470 Column() { 471 Column() { 472 Text('preview-builder') 473 .width(200) 474 .height(100) 475 .textAlign(TextAlign.Center) 476 .margin(100) 477 .fontSize(30) 478 .bindContextMenu(this.isShown, this.MyMenu, 479 { 480 preview: this.MyPreview, 481 onDisappear: ()=>{ 482 this.isShown = false; 483 } 484 }) 485 Button('click') 486 .onClick(()=>{ 487 this.isShown = true; 488 }) 489 } 490 }.width('100%') 491 } 492 } 493} 494``` 495 496### Example 8: Using Custom Menu and Preview Animations 497 498This example demonstrates how to use **bindContextMenu** with custom animations for the menu and preview. 499 500```ts 501// xxx.ets 502@Entry 503@Component 504struct MenuExample { 505 @Builder MenuBuilder() { 506 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 507 Text('Test menu item 1') 508 .fontSize(12) 509 .width(200) 510 .height(30) 511 .textAlign(TextAlign.Center) 512 Divider().height(10) 513 Text('Test menu item 2') 514 .fontSize(12) 515 .width(100) 516 .height(30) 517 .textAlign(TextAlign.Center) 518 }.width(100) 519 } 520 @Builder 521 MyPreview() { 522 Column() { 523 Image($r('app.media.icon')) 524 .width(50) 525 .height(50) 526 } 527 } 528 @State isShow:boolean = false 529 private iconStr: ResourceStr = $r("app.media.icon") 530 531 @Builder 532 MyMenu() { 533 Menu() { 534 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 535 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 536 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 537 } 538 } 539 build() { 540 Column() { 541 Button('LongPress bindContextMenu') 542 .margin({ top: 15 }) 543 .bindContextMenu( 544 this.MenuBuilder, 545 ResponseType.LongPress,{ 546 transition: TransitionEffect.OPACITY.animation({ duration: 4000, curve: Curve.Ease }).combine( 547 TransitionEffect.rotate({ z: 1, angle: 180 })), 548 preview: this.MyPreview, 549 previewAnimationOptions: { 550 scale: [0.8, 1.0], 551 transition: TransitionEffect.OPACITY.animation({ duration: 4000, curve: Curve.Ease }).combine( 552 TransitionEffect.rotate({ z: 1, angle: 180 })) 553 } 554 }) 555 } 556 .width('100%') 557 .margin({ top: 5 }) 558 } 559} 560``` 561 562 563 564### Example 9: Setting the Symbol Icon 565 566This example shows how to use **bindMenu** with **symbolIcon** to display a menu with symbol icons. 567 568```ts 569// xxx.ets 570import { SymbolGlyphModifier } from '@kit.ArkUI'; 571@Entry 572@Component 573struct MenuExample { 574 @State symbolIconModifier1: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.ohos_photo')).fontSize('24vp'); 575 @State symbolIconModifier2: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.ohos_photo')).fontSize('24vp'); 576 build() { 577 Column() { 578 Text('click for Menu') 579 } 580 .width('100%') 581 .margin({ top: 5 }) 582 .bindMenu([ 583 { 584 value: 'Menu1', 585 symbolIcon:this.symbolIconModifier1, 586 action: () => { 587 console.info('handle Menu1 select') 588 } 589 }, 590 { 591 value: 'Menu2', 592 symbolIcon:this.symbolIconModifier2, 593 action: () => { 594 console.info('handle Menu2 select') 595 } 596 }, 597 ]) 598 } 599} 600``` 601 602 603 604### Example 10: Using Shared Element Transition 605 606This example demonstrates how to use **bindContextMenu** with **hoverScale** to create a shared element transition effect from the component screenshot to the custom preview. 607 608```ts 609// xxx.ets 610@Entry 611@Component 612struct Index { 613 private iconStr: ResourceStr = $r("app.media.app_icon") 614 615 @Builder 616 MyMenu() { 617 Menu() { 618 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 619 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 620 MenuItem({ startIcon: this.iconStr, content: "Menu option" }) 621 } 622 } 623 624 @Builder 625 MyPreview() { 626 Column() { 627 Image($r('app.media.example')) 628 .width(200) 629 .height(200) 630 } 631 } 632 633 build() { 634 Column({ space: 50 }) { 635 Column() { 636 Column() { 637 Image($r('app.media.example')) 638 .width(100) 639 .height(100) 640 .margin(100) 641 .bindContextMenu(this.MyMenu, ResponseType.LongPress, 642 { 643 preview: this.MyPreview, 644 previewAnimationOptions: { 645 hoverScale: [1.0, 0.95] 646 } 647 }) 648 } 649 }.width('100%') 650 } 651 } 652} 653``` 654 655 656