• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 菜单控制
2
3为组件绑定弹出式菜单,弹出式菜单以垂直列表形式显示菜单项,可通过长按、点击或鼠标右键触发。
4
5>  **说明:**
6>
7>  - 从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9>  - CustomBuilder里不支持再使用bindMenu、bindContextMenu弹出菜单。多级菜单可使用[Menu组件](ts-basic-components-menu.md)。
10>
11>  - 弹出菜单的文本内容不支持长按选中。
12
13## bindMenu
14
15bindMenu(content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
16
17给组件绑定菜单,点击后弹出菜单。弹出菜单项支持图标+文本排列和自定义两种功能。
18
19**系统能力:** SystemCapability.ArkUI.ArkUI.Full
20
21**参数:**
22
23| 参数名  | 类型                                                         | 必填 | 说明                                         |
24| ------- | ------------------------------------------------------------ | ---- | -------------------------------------------- |
25| content | Array<[MenuElement](#menuelement)&gt;&nbsp;\|&nbsp;[CustomBuilder](ts-types.md#custombuilder8) | 是   | 配置菜单项图标和文本的数组,或者自定义组件。 |
26| options | [MenuOptions](#menuoptions10)                                | 否   | 配置弹出菜单的参数。                         |
27
28## bindMenu<sup>11+</sup>
29
30bindMenu(isShow: boolean, content: Array<MenuElement&gt; | CustomBuilder, options?: MenuOptions)
31
32给组件绑定菜单,点击后弹出菜单。弹出菜单项支持图标+文本排列和自定义两种功能。
33
34**系统能力:** SystemCapability.ArkUI.ArkUI.Full
35
36**参数:**
37
38| 参数名               | 类型                                                         | 必填 | 说明                                                         |
39| -------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
40| isShow<sup>11+</sup> | boolean                                                      | 是   | 支持开发者通过状态变量控制显隐,默认值为false,menu弹窗必须等待页面全部构建才能展示,因此不能在页面构建中设置为true,否则会导致显示位置及形状错误,当前不支持双向绑定。 |
41| content              | Array<[MenuElement](#menuelement)&gt;&nbsp;\|&nbsp;[CustomBuilder](ts-types.md#custombuilder8) | 是   | 配置菜单项图标和文本的数组,或者自定义组件。                 |
42| options              | [MenuOptions](#menuoptions10)                                | 否   | 配置弹出菜单的参数。                                         |
43
44## bindContextMenu<sup>8+</sup>
45
46bindContextMenu(content: CustomBuilder, responseType: ResponseType, options?: ContextMenuOptions)
47
48给组件绑定菜单,触发方式为长按或者右键点击,弹出菜单项需要自定义。
49
50**系统能力:** SystemCapability.ArkUI.ArkUI.Full
51
52**参数:**
53
54| 参数名       | 类型                                               | 必填 | 说明                                         |
55| ------------ | -------------------------------------------------- | ---- | -------------------------------------------- |
56| content      | [CustomBuilder](ts-types.md#custombuilder8)        | 是   | 配置菜单项图标和文本的数组,或者自定义组件。 |
57| responseType | [ResponseType](ts-appendix-enums.md#responsetype8) | 是   | 菜单弹出条件,长按或者右键点击。             |
58| options      | [ContextMenuOptions](#contextmenuoptions10)        | 否   | 配置弹出菜单的参数。                         |
59
60## MenuElement
61
62| 名称                  | 类型                                   | 必填 | 描述                                                         |
63| --------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
64| value                 | [ResourceStr](ts-types.md#resourcestr) | 是   | 菜单项文本。                                                 |
65| icon<sup>10+</sup>    | [ResourceStr](ts-types.md#resourcestr) | 否   | 菜单项图标。                                                 |
66| enabled<sup>11+</sup> | boolean                                | 否   | 菜单条目是否可进行交互。<br/>默认值:true, 菜单条目可以进行交互。 |
67| action                | ()&nbsp;=&gt;&nbsp;void                | 是   | 点击菜单项的事件回调。                                       |
68
69## MenuOptions<sup>10+</sup>
70
71继承自[ContextMenuOptions](#contextmenuoptions10)。
72
73| 名称                          | 类型                                   | 必填 | 描述                                                         |
74| ----------------------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
75| title                         | [ResourceStr](ts-types.md#resourcestr) | 否   | 菜单标题。<br>**说明:**<br/>仅在content设置为Array<[MenuElement](#menuelement)&gt; 时生效。 |
76| showInSubWindow<sup>11+</sup> | boolean                                | 否   | 是否在子窗口显示菜单。<br/>默认值:2in1设备为true,其他设备为false。                     |
77
78## ContextMenuOptions<sup>10+</sup>
79
80| 名称                  | 类型                                                         | 必填 | 描述                                                         |
81| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
82| offset                | [Position](ts-types.md#position8)                            | 否   | 菜单弹出位置的偏移量,不会导致菜单显示超出屏幕范围。<br/>**说明:**<br />菜单类型为相对⽗组件区域弹出时,⾃动根据菜单位置属性 (placement)将区域的宽或⾼计⼊偏移量中。<br/>当菜单相对父组件出现在上侧时(placement设置为Placement.TopLeftPlacement.TopPlacement.TopRight),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向上进行偏移。<br/>当菜单相对父组件出现在下侧时(placement设置为Placement.BottomLeftPlacement.BottomPlacement.BottomRight),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>当菜单相对父组件出现在左侧时(placement设置为Placement.LeftTopPlacement.LeftPlacement.LeftBottom),x为正值,菜单相对组件向左进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>当菜单相对父组件出现在右侧时(placement设置为Placement.RightTopPlacement.RightPlacement.RightBottom),x为正值,菜单相对组件向右进行偏移,y为正值,菜单相对组件向下进行偏移。<br/>如果菜单调整了显示位置(与placement初始值主方向不⼀致),则偏移值 (offset) 失效。 |
83| placement             | [Placement](ts-appendix-enums.md#placement8)                 | 否   | 菜单组件优先显示的位置,当前位置显示不下时,会自动调整位置。<br/>**说明:**<br />placement值设置为undefined、null或没有设置此选项时,按未设置placement处理,当使用[bindContextMenu<sup>8+</sup>](#bindcontextmenu8),菜单跟随点击位置弹出。 |
84| enableArrow           | boolean                                                      | 否   | 是否显示箭头。如果菜单的大小和位置不足以放置箭头时,不会显示箭头。 <br/>默认值:false, 不显示箭头。<br/>**说明:**<br />enableArrow为true时,placement未设置或者值为非法值,默认在目标物上方显示,否则按照placement的位置优先显示。当前位置显示不下时,会自动调整位置,enableArrow为undefined时,不显示箭头。 |
85| arrowOffset           | [Length](ts-types.md#length)                                 | 否   | 箭头在菜单处的偏移。箭头在菜单水平方向时,偏移量为箭头至最左侧的距离,默认居中。箭头在菜单竖直方向时,偏移量为箭头至最上侧的距离,默认居中。偏移量必须合法且转换为具体数值时大于0才会生效,另外该值生效时不会导致箭头超出菜单四周的安全距离。根据配置的placement来计算是在水平还是竖直方向上偏移。 |
86| preview<sup>11+</sup> | [MenuPreviewMode](ts-appendix-enums.md#menupreviewmode11)\|&nbsp;[CustomBuilder](ts-types.md#custombuilder8) | 否   | 默认值:MenuPreviewMode.NONE, 无预览内容。<br/>**说明:**<br />- 不支持responseType为ResponseType.RightClick时触发,如果responseType为ResponseType.RightClick,则不会显示预览内容。<br />- 当未设置preview参数或preview参数设置为MenuPreviewMode.NONE时,enableArrow参数生效。<br />- 当preview参数设置为MenuPreviewMode.IMAGE或CustomBuilder时,enableArrow为true时也不显示箭头。 |
87| previewAnimationOptions<sup>11+</sup> | [ContextMenuAnimationOptions](#contextmenuanimationoptions11) | 否    | 控制长按预览显示动画开始倍率和结束倍率(相对预览原图比例)。<br/>默认值:{scale: [0.95, 1.1]}。<br/>**说明:**<br />-倍率设置参数小于等于0时,不生效。<br />-当前只在preview设置为MenuPreviewMode.IMAGE模式时生效。 |
88| onAppear              | ()&nbsp;=&gt;&nbsp;void                                      | 否   | 菜单弹出时的事件回调。                                       |
89| onDisappear           | ()&nbsp;=&gt;&nbsp;void                                      | 否   | 菜单消失时的事件回调。                                       |
90| aboutToAppear              | ()&nbsp;=&gt;&nbsp;void                                      | 否   | 菜单显示动效前的事件回调。                                       |
91| aboutToDisappear           | ()&nbsp;=&gt;&nbsp;void                                      | 否   | 菜单退出动效前的事件回调。                                       |
92| backgroundColor<sup>11+</sup> | [ResourceColor](ts-types.md#resourcecolor)  | 否 | 弹窗背板颜色。<br/>默认值:Color.Transparent。 |
93| backgroundBlurStyle<sup>11+</sup> | [BlurStyle](ts-appendix-enums.md#blurstyle9) | 否 | 弹窗背板模糊材质。<br/>默认值:BlurStyle.COMPONENT_ULTRA_THICK。 |
94
95## ContextMenuAnimationOptions<sup>11+</sup>
96
97| 名称  | 类型                                       | 必填 | 描述                                 |
98| ----- | ------------------------------------------ | ---- | ------------------------------------ |
99| scale | [AnimationRange](#animationrange11)\<number> | 否   | 动画开始和结束时相对预览原图缩放比例。 |
100
101## AnimationRange<sup>11+</sup>
102
103表示动画开始和结束时相对预览原图缩放比例。
104
105系统能力:SystemCapability.ArkUI.ArkUI.Full
106
107| 取值范围         | 说明                                                                           |
108| ---------------- | ------------------------------------------------------------------------------ |
109| [from: T, to: T] | from表示动画开始时相对预览原图缩放比例,to表示动画结束时相对预览原图缩放比例。 |
110
111## 示例
112
113### 示例1
114
115普通菜单
116
117```ts
118// xxx.ets
119@Entry
120@Component
121struct MenuExample {
122  build() {
123    Column() {
124      Text('click for Menu')
125    }
126    .width('100%')
127    .margin({ top: 5 })
128    .bindMenu([
129      {
130        value: 'Menu1',
131        action: () => {
132          console.info('handle Menu1 select')
133        }
134      },
135      {
136        value: 'Menu2',
137        action: () => {
138          console.info('handle Menu2 select')
139        }
140      },
141    ])
142  }
143}
144```
145
146![zh-cn_image_0000001174582862](figures/zh-cn_image_0000001174582862.gif)
147
148### 示例2
149
150自定义内容菜单
151
152```ts
153@Entry
154@Component
155struct MenuExample {
156  @State listData: number[] = [0, 0, 0]
157
158  @Builder MenuBuilder() {
159    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
160      ForEach(this.listData, (item:number, index) => {
161        Column() {
162          Row() {
163            Image($r("app.media.icon")).width(20).height(20).margin({ right: 5 })
164            Text(`Menu${index as number + 1}`).fontSize(20)
165          }
166          .width('100%')
167          .height(30)
168          .justifyContent(FlexAlign.Center)
169          .align(Alignment.Center)
170          .onClick(() => {
171            console.info(`Menu${index as number + 1} Clicked!`)
172          })
173
174          if (index != this.listData.length - 1) {
175            Divider().height(10).width('80%').color('#ccc')
176          }
177        }.padding(5).height(40)
178      })
179    }.width(100)
180  }
181
182  build() {
183    Column() {
184      Text('click for menu')
185        .fontSize(20)
186        .margin({ top: 20 })
187        .bindMenu(this.MenuBuilder)
188    }
189    .height('100%')
190    .width('100%')
191    .backgroundColor('#f0f0f0')
192  }
193}
194```
195
196![zh-cn_image_0000001186807708](figures/zh-cn_image_0000001186807708.gif)
197
198### 示例3
199
200菜单(长按触发显示)
201
202```ts
203// xxx.ets
204@Entry
205@Component
206struct ContextMenuExample {
207  @Builder MenuBuilder() {
208    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
209      Text('Test menu item 1')
210        .fontSize(20)
211        .width(100)
212        .height(50)
213        .textAlign(TextAlign.Center)
214      Divider().height(10)
215      Text('Test menu item 2')
216        .fontSize(20)
217        .width(100)
218        .height(50)
219        .textAlign(TextAlign.Center)
220    }.width(100)
221  }
222
223  build() {
224    Column() {
225      Text('LongPress for menu')
226    }
227    .width('100%')
228    .margin({ top: 5 })
229    .bindContextMenu(this.MenuBuilder, ResponseType.LongPress)
230  }
231}
232```
233
234![longMenu](figures/longMenu.gif)
235
236### 示例4
237
238指向性菜单(右键触发显示)
239
240```ts
241// xxx.ets
242@Entry
243@Component
244struct DirectiveMenuExample {
245  @Builder MenuBuilder() {
246    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
247      Text('Options')
248      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
249      Text('Hide')
250      Divider().strokeWidth(2).margin(5).color('#F0F0F0')
251      Text('Exit')
252    }
253    .width(200)
254  }
255
256  build() {
257    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
258      Column() {
259        Text("DirectiveMenuExample")
260          .fontSize(20)
261          .width('100%')
262          .height("25%")
263          .backgroundColor('#F0F0F0')
264          .textAlign(TextAlign.Center)
265          .bindContextMenu(this.MenuBuilder, ResponseType.RightClick, {
266            enableArrow: true,
267            placement: Placement.Bottom
268          })
269      }
270    }
271    .width('100%')
272    .height('100%')
273  }
274}
275```
276
277![zh-cn_image_0000001689126950](figures/zh-cn_image_0000001689126950.png)
278
279### 示例5
280
281长按悬浮菜单(预览内容为截图形式)
282
283```ts
284// xxx.ets
285@Entry
286@Component
287struct Index {
288  private iconStr: ResourceStr = $r("app.media.icon")
289
290  @Builder
291  MyMenu() {
292    Menu() {
293      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
294      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
295      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
296    }
297  }
298
299  build() {
300    Column({ space: 50 }) {
301      Column() {
302        Column() {
303          Text('preview-image')
304            .width(200)
305            .height(100)
306            .textAlign(TextAlign.Center)
307            .margin(100)
308            .fontSize(30)
309            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
310              { preview: MenuPreviewMode.IMAGE,
311                previewAnimationOptions: {scale: [0.8, 1.0]},
312              })
313            .backgroundColor("#ff3df2f5")
314        }
315      }.width('100%')
316    }
317  }
318}
319```
320
321![preview-image](figures/preview-image.png)
322
323### 示例6
324
325长按悬浮菜单(自定义预览内容)
326
327```ts
328// xxx.ets
329@Entry
330@Component
331struct Index {
332  private iconStr: ResourceStr = $r("app.media.icon")
333
334  @Builder
335  MyMenu() {
336    Menu() {
337      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
338      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
339      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
340    }
341  }
342
343  @Builder
344  MyPreview() {
345    Column() {
346      Image($r('app.media.icon'))
347        .width(200)
348        .height(200)
349    }
350  }
351
352  build() {
353    Column({ space: 50 }) {
354      Column() {
355        Column() {
356          Text('preview-builder')
357            .width(200)
358            .height(100)
359            .textAlign(TextAlign.Center)
360            .margin(100)
361            .fontSize(30)
362            .bindContextMenu(this.MyMenu, ResponseType.LongPress,
363              {
364                preview: this.MyPreview
365              })
366        }
367      }.width('100%')
368    }
369  }
370}
371```
372
373![preview-builder](figures/preview-builder.png)
374
375### 示例7
376
377通过绑定isShown控制菜单(自定义预览内容)
378
379```ts
380// xxx.ets
381@Entry
382@Component
383struct Index {
384  private iconStr: ResourceStr = $r("app.media.icon")
385  @State isShown: boolean = false
386
387  @Builder
388  MyMenu() {
389    Menu() {
390      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
391      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
392      MenuItem({ startIcon: this.iconStr, content: "菜单选项" })
393    }
394  }
395
396  @Builder
397  MyPreview() {
398    Column() {
399      Image($r('app.media.icon'))
400        .width(200)
401        .height(200)
402    }
403  }
404
405  build() {
406    Column({ space: 50 }) {
407      Column() {
408        Column() {
409          Text('preview-builder')
410            .width(200)
411            .height(100)
412            .textAlign(TextAlign.Center)
413            .margin(100)
414            .fontSize(30)
415            .bindContextMenu(this.isShown, this.MyMenu,
416              {
417                preview: this.MyPreview,
418                onDisappear: ()=>{
419                    this.isShown = false;
420                }
421              })
422          Button('click')
423            .onClick(()=>{
424                this.isShown = true;
425             })
426        }
427      }.width('100%')
428    }
429  }
430}
431```
432