diff --git a/examples/Menu/entry/src/main/ets/customBuilder/MenuBuilder.ets b/examples/Menu/entry/src/main/ets/customBuilder/MenuBuilder.ets index 3a122bc70b94e2dee0d1daf7ba691fb168772e28..ebda627c6124b834dc51aef0ad35224ebe46d042 100644 --- a/examples/Menu/entry/src/main/ets/customBuilder/MenuBuilder.ets +++ b/examples/Menu/entry/src/main/ets/customBuilder/MenuBuilder.ets @@ -180,4 +180,51 @@ export struct CustomMenuBuilder { .borderRadius(16) .borderColor(Color.Blue) } +} + +@Preview +@Component +export struct SimpleSubMenuBuilder { + build() { + Menu(){ + MenuItem({ startIcon: startIcon, content: '复制' }) + .enabled(false) + MenuItem({ + symbolStartIcon: symbolStartIcon, + labelInfo: '粘贴', + symbolEndIcon: symbolEndIcon, + }) + } + } +} + +@Preview +@Component +export struct SimpleMenuBuilder { + @State menuAttrOptions: MenuAttrOptions = { + submenuMode: 0, + menuItemDivider: undefined, + menuItemGroupDivider: undefined + } + @Builder + SubMenuBuilder() { + SimpleSubMenuBuilder() + } + build() { + Menu(){ + MenuItem({startIcon: startIcon, content: '选项' }) + .enabled(true) + MenuItem({ + symbolStartIcon: symbolStartIcon, + content: "次级", + builder:this.SubMenuBuilder() + }) + } + .font(this.menuAttrOptions.font) + .fontColor(this.menuAttrOptions.fontColor) + .radius(this.menuAttrOptions.radius) + .subMenuExpandingMode(this.menuAttrOptions.submenuMode) + .menuItemDivider(this.menuAttrOptions.menuItemDivider) + .menuItemGroupDivider(this.menuAttrOptions.menuItemGroupDivider) + } } \ No newline at end of file diff --git a/examples/Menu/entry/src/main/ets/pages/Examples/Index.ets b/examples/Menu/entry/src/main/ets/pages/Examples/Index.ets index 239937b3172abe34d75054f1b7ad9ed663bb8f95..b3ba3a6c52587f6ea95028f21d17239e515a347e 100644 --- a/examples/Menu/entry/src/main/ets/pages/Examples/Index.ets +++ b/examples/Menu/entry/src/main/ets/pages/Examples/Index.ets @@ -41,7 +41,11 @@ struct Index { { title: "示例15:菜单基本功能_4_避让", url: "pages/Examples/MenuTestLevel0_4" }, { title: "示例16:菜单基本功能_5_箭头", url: "pages/Examples/MenuTestLevel0_5" }, { title: "示例17:菜单基本功能_6_布局边距", url: "pages/Examples/MenuTestLevel0_6" }, - { title: "示例18:菜单基本功能_18_预览图缩放/布局", url: "pages/Examples/MenuTestLevel0_18" }, + { title: "示例18:菜单基本功能_9_radius", url: "pages/Examples/MenuTestLevel0_12" }, + { title: "示例19:菜单基本功能_11_预览图弹出方式/类型", url: "pages/Examples/MenuTestLevel0_16" }, + { title: "示例20:菜单基本功能_12_预览图scale/hoverScale", url: "pages/Examples/MenuTestLevel0_17" }, + { title: "示例21:菜单基本功能_13_预览图尺寸/圆角", url: "pages/Examples/MenuTestLevel0_18" }, + { title: "示例22:菜单基本功能_18_预览图缩放/布局", url: "pages/Examples/MenuTestLevel0_24" }, ] build() { diff --git a/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_12.ets b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_12.ets new file mode 100644 index 0000000000000000000000000000000000000000..8b0ca8c445bb82a66a0e33c30f0161751a821a58 --- /dev/null +++ b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_12.ets @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * bindMenu和bindContextMenu验证菜单的边框圆角半径 + */ + +import { MyComponent } from '../../common/MyComponent' + +@Extend(Text) +function paramTextStyle() { + .fontSize(9) + .width('100%') +} + +@Extend(Text) +function componentTextStyle() { + .fontSize(15) + .backgroundColor(Color.Orange) + .margin(3) + .padding(3) + .borderWidth(1.0) +} + +@Extend(Column) +function columnStyle() { + .borderWidth(1.0) + .padding(5) + .width('100%') + .backgroundColor(Color.Pink) +} + +@Entry +@Component +struct MenuTestLevel0_12 { + scroller: Scroller = new Scroller() + @State index: number[] = [0, 0,] + @State menuShow: boolean[] = [false, false, false, false, false] + @State extremeMenuRadius: number = 60 + private iconStr: ResourceStr = $r('app.media.app_icon') + private iconStr2: ResourceStr = $r('app.media.app_icon') + + // 次级菜单 + @Builder + SubMenu() { + Menu() { + MenuItem({ content: '复制', labelInfo: 'Ctrl+C' }) + MenuItem({ content: '粘贴', labelInfo: 'Ctrl+V' }) + } + .backgroundColor('#C2B1C8') + .borderWidth(1.0) + .borderRadius(10) + } + + @Builder + MenuBuilder_Radius() { + Menu() { + MenuItem({ startIcon: $r('app.media.app_icon'), content: '菜单选项' }) + MenuItem({ startIcon: $r('app.media.app_icon'), content: '菜单选项' }) + .enabled(false) + MenuItem({ + startIcon: this.iconStr, + content: '次级菜单', + endIcon: this.iconStr2, + builder: (): void => this.SubMenu() + }) + } + .backgroundColor('#C2B1C8') + .borderWidth(1.0) + .borderRadius(10) + } + + // BorderRadius bindMenu/bindContextMenu CustomBuilder + @Builder + CustomMenuBuilder_Radius() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Options') + Divider().strokeWidth(1).margin(5).color('#ff414141') + Text('Hide') + Divider().strokeWidth(1).margin(5).color('#ff414141') + Text('Exit') + } + .width('70%') + .backgroundColor('#C2B1C8') + .borderWidth(1.0) + .borderRadius(10) + } + + // menu preview + @Builder + MenuPreviewBuilder() { + Column() { + Image($r('app.media.app_icon')) + .width(160) + .height(120) + .margin(10) + } + .borderWidth(1.0) + .borderRadius(10) + } + + // borderRadius TestList + @State menuBorderRadiusTestList: (ContextMenuOptions | undefined)[] = [ + //1 + , + //2 + { + borderRadius: undefined + }, + //3 + { + borderRadius: { + topLeft: '20vp', + topRight: '20px', + bottomLeft: '20fp', + bottomRight: '20lpx' + }, + }, + //4 + { + borderRadius: { + topLeft: '-20', + topRight: '0', + bottomLeft: '20', + bottomRight: '36' + }, + }, + //5 + { + borderRadius: { + topLeft: 20, + topRight: $r('app.float.float_10'), + bottomLeft: '20', + bottomRight: '20%' + }, //百分比不生效. + }, + //6 + { + borderRadius: { + topLeft: '60aa', + topRight: $r('app.string.EntryAbility_label'), + bottomLeft: undefined, + bottomRight: '30%' + }, //预期都为默认值. + }, + //7 + { + borderRadius: 32, + }, + //8 + { + borderRadius: '32px', + }, + //9 + { + borderRadius: '32lpx', + }, + //10 + { + borderRadius: '32fp', + }, + //11 + { + borderRadius: '32vp', + }, + //12 + { + borderRadius: -32, + }, + //13 + { + borderRadius: 0, + }, + //14 + { + borderRadius: $r('app.float.float_60'), + }, + //15 + { + borderRadius: $r('app.string.EntryAbility_label'), + }, + //16 + { + borderRadius: '90px', + }, + ] + + build() { + Scroll(this.scroller) { + Column({ space: 5 }) { + Text(`bindMenu和bindContextMenu验证菜单的边框圆角半径`) + .paramTextStyle() + Column({ space: 5 }) { + Text(`bindMenu/bindContextMenu不设置边框圆角半径`) + .paramTextStyle() + Text(`bindMenu_Array: unset_borderRadius`) + .componentTextStyle() + .bindMenu([ + { + value: 'Menu1', + action: () => { + console.info('handle Menu1 select') + } + }, + { + value: 'Menu2', + action: () => { + console.info('handle Menu2 select') + } + }, + ]) + Text(`bindMenu_Menu: unset_borderRadius`) + .componentTextStyle() + .bindMenu(this.MenuBuilder_Radius()) + Text(`bindContextMenu_Custom: unset_borderRadius`) + .componentTextStyle() + .fontSize(13) + .bindContextMenu(this.CustomMenuBuilder_Radius(), ResponseType.LongPress) + } + .columnStyle() + + Column({ space: 5 }) { + Text(`bindMenu/bindContextMenu设置边框圆角半径`) + .paramTextStyle() + Row({ space: 2 }) { + Text(`${this.index[0] + 1}` + ' / ') + .fontSize(9) + Text(`${this.menuBorderRadiusTestList.length}`) + .key('paramSets_key_0') + .fontSize(9) + MyComponent({ + title: 'Test0+', func: () => { + this.index[0]++ + if (this.index[0] == this.menuBorderRadiusTestList.length) { + this.index[0] = 0 + } + } + }) + MyComponent({ + title: 'Test0-', func: () => { + this.index[0]-- + if (this.index[0] <= -1) { + this.index[0] = this.menuBorderRadiusTestList.length - 1 + } + } + }) + } + + Text(`bindMenu_Array: set_borderRadius`) + .componentTextStyle() + .bindMenu([ + { + value: 'Menu1', + action: () => { + console.info('handle Menu1 select') + } + }, + { + value: 'Menu2', + action: () => { + console.info('handle Menu2 select') + } + }, + ], { + borderRadius: this.menuBorderRadiusTestList[this.index[0]]?.borderRadius, + //bindMenu: borderRadius和Arrow组合测试 + enableArrow: true, + arrowOffset: '25%', + backgroundColor: '#fffdd986', + backgroundBlurStyle: BlurStyle.NONE, + }) + Text(`bindMenu_Custom: set_borderRadius`) + .componentTextStyle() + .bindMenu(this.CustomMenuBuilder_Radius(), { + borderRadius: this.menuBorderRadiusTestList[this.index[0]]?.borderRadius, + backgroundColor: '#4A4333', + backgroundBlurStyle: BlurStyle.NONE, + }) + Text(`bindContextMenu_Menu: set_borderRadius`) + .componentTextStyle() + .fontSize(13) + .bindContextMenu(this.MenuBuilder_Radius(), ResponseType.LongPress, { + borderRadius: this.menuBorderRadiusTestList[this.index[0]]?.borderRadius, + backgroundColor: '#4A4333', + backgroundBlurStyle: BlurStyle.NONE, + preview: this.MenuPreviewBuilder(), + }) + } + .columnStyle() + } + .width('100%') + } + .padding(12) + .align(Alignment.TopStart) + .width('100%').height('100%') + } +} \ No newline at end of file diff --git a/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_16.ets b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_16.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f23ec33bc9d039f885fdc9c425c84f15013a911 --- /dev/null +++ b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_16.ets @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * bindContextMenu设置预览图菜单 + * 验证BindContextMenu的类型和预览图绘制 + */ + +import { MyComponent } from '../../common/MyComponent' + +class SizeOption { + public width?: Length = '240' + public height?: Length = '300' +} + +@Extend(Text) +function paramTextStyle() { + .fontSize(9) + .width('100%') +} + +@Extend(Text) +function componentStyle() { + .backgroundColor(Color.Orange) + .textAlign(TextAlign.Center) +} + +@Extend(Column) +function columnStyle() { + .borderWidth(1.0) + .padding(5) + .width('100%') + .backgroundColor(Color.Pink) +} + +@Entry +@Component +struct MenuTestLevel0_16 { + //ets layout + scroller: Scroller = new Scroller() + @State index: number[] = [0, 0, 0, 0, 0,] + //菜单交互优化 + @State menuShow: boolean[] = [false, false, false] + + //Menu Builder + @Builder + MenuBuilder() { + Menu() { + MenuItem({ content: '复制', labelInfo: 'Ctrl+C' }) + MenuItem({ content: '粘贴', labelInfo: 'Ctrl+V' }) + } + } + + //预览图菜单自定义预览图 + @Builder + MenuPreviewBuilder() { + Image($r('app.media.app_icon')) + .width(160) + .height(100) + } + + //Menu菜单:设置不同的高度、宽度 + @Builder + MenuBuilderSized($$: SizeOption) { + Menu() { + MenuItem({ content: '复制', labelInfo: 'Ctrl+C' }) + MenuItem({ content: '粘贴', labelInfo: 'Ctrl+V' }) + MenuItem({ content: '复制', labelInfo: 'Ctrl+C' }) + MenuItem({ content: '粘贴', labelInfo: 'Ctrl+V' }) + } + .borderWidth(1.0) + .height($$.height) + .width($$.width) + } + + //different size preview + @Builder + MenuPreviewBuilderSized($$: SizeOption) { + Column() { + Image($r('app.media.app_icon')) + } + .width($$.width) + .height($$.height) + } + + @State previewBuilderSizeOptions: SizeOption = { + width: 240, + height: 160 + } + //menuPreviewMode test list + @State menuPreviewModeTestList: (MenuPreviewMode | CustomBuilder | undefined)[] = [ + //1 + MenuPreviewMode.NONE, //无预览图,无蒙层 + //2 + MenuPreviewMode.IMAGE, + //3 + undefined, ////无预览图,无蒙层 + //4 + 7, + ] + + build() { + Scroll(this.scroller) { + Column({ space: 5 }) { + //bindContextMenu longPress类型不设置自定义预览图 + Text('验证bindContextMenu的类型和预览图绘制') + .paramTextStyle() + Column({ space: 5 }) { + Text('contextMenu设置longPress / show, 不设置preview') + .paramTextStyle() + Text('contextMenu: \nlongPress_unsetPreview') + .key('contextMenu: longPress_unsetPreview') + .componentStyle() + .bindContextMenu(this.MenuBuilder(), ResponseType.LongPress, { + enableArrow: true, + }) + Text('contextMenu: \nsetShow_unsetPreview') + .key('contextMenu:setShow_unsetPreview') + .componentStyle() + .bindContextMenu(this.menuShow[0], this.MenuBuilder(), { + enableArrow: true, + onDisappear: () => { + this.menuShow[0] = false + } + }) + .onClick(() => { + this.menuShow[0] = true + }) + + Text(`bindContextMenu设置rightClick, 设置preview`) + .paramTextStyle() + Text('contextMenu: \nrightClick_preview') + .key(`contextMenu: rightClick_preview`) + .componentStyle() + .bindContextMenu(this.MenuBuilder(), ResponseType.RightClick, { + preview: MenuPreviewMode.IMAGE, //预期无预览图,没有蒙层 + enableArrow: true, + }) + } + .columnStyle() + + Column({ space: 5 }) { + Text(`bindContextMenu设置longPress/show, 设置preview`) + .paramTextStyle() + Row({ space: 2 }) { + Text(`${this.index[0] + 1}` + ' / ') + .fontSize(9) + Text(`${this.menuPreviewModeTestList.length}`) + .key('paramSets_key_0') + .fontSize(9) + MyComponent({ + title: 'Test0+', func: () => { + this.index[0]++ + if (this.index[0] == this.menuPreviewModeTestList.length) { + this.index[0] = 0 + } + } + }) + MyComponent({ + title: 'Test0-', func: () => { + this.index[0]-- + if (this.index[0] <= -1) { + this.index[0] = this.menuPreviewModeTestList.length - 1 + } + } + }) + } + + Text('contextMenu: \nlongPress_preview') + .key(`contextMenu: longPress_preview`) + .componentStyle() + .bindContextMenu(this.MenuBuilder(), ResponseType.LongPress, { + preview: this.menuPreviewModeTestList[this.index[0]], + enableArrow: true, + }) + Text('contextMenu: \nshow_preview') + .key(`contextMenu: show_preview`) + .componentStyle() + .bindContextMenu(this.menuShow[1], this.MenuBuilder(), { + preview: this.menuPreviewModeTestList[this.index[0]], + enableArrow: true, + onDisappear: () => { + this.menuShow[1] = false + } + }) + .onClick(() => { + this.menuShow[1] = true + }) + } + .columnStyle() + + Column({ space: 5 }) { + Text(`preview设置自定义预览图的绘制效果`) + .paramTextStyle() + Image($r('app.media.app_icon')) + .key(`contextMenu: previewCustom`) + .width('120').height(45) + .bindContextMenu(this.MenuBuilderSized({ width: 200 }), ResponseType.LongPress, { + preview: this.MenuPreviewBuilderSized({ + width: this.previewBuilderSizeOptions.width, + height: this.previewBuilderSizeOptions.height + }) + }) + } + .columnStyle() + } + .width('100%') + } + .padding(12) + .align(Alignment.TopStart) + .width('100%').height('100%') + } +} \ No newline at end of file diff --git a/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_17.ets b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_17.ets new file mode 100644 index 0000000000000000000000000000000000000000..8a3194405c44dc4b1b37650f3171515b93f2f6d5 --- /dev/null +++ b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_17.ets @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * bindContextMenu设置预览图菜单 + * 验证bindContextMenu设置预览图和previewAnimationOptions: scale和hoverScale + */ + +import { MyComponent } from '../../common/MyComponent' + +@Extend(Text) function paramTextStyle() { + .fontSize(9) + .width('100%') +} +@Extend(Column) function columnStyle() { + .borderWidth(1.0) + .padding(5) + .width('100%') + .backgroundColor(Color.Pink) +} +@Entry +@Component +struct MenuTestLevel0_17 { + //ets layout + scroller: Scroller = new Scroller() + @State index: number[] = [0, 0, 0, 0, 0, ] + //菜单交互优化 + @State menuShow: boolean[] = [false, false, false] + //Menu Builder + @Builder + MenuBuilder() { + Menu() { + MenuItem({ content: '复制', labelInfo: 'Ctrl+C' }) + MenuItem({ content: '粘贴', labelInfo: 'Ctrl+V' }) + } + } + //预览图菜单自定义预览图 + @Builder MenuPreviewBuilder() { + Image($r('app.media.app_icon')) + .width(160) + .height(100) + } + // previewAnimationOptions test list + @State menuPreviewAnimationOptionsTestList: (ContextMenuAnimationOptions | undefined) [] = [ + //1 + { + scale: undefined, + hoverScale: undefined + }, + //2 + { + scale: [0.95, 1.1], + hoverScale: [0.8, 1.2] + }, + //3 + { + scale: [-1.0, 2.0], + hoverScale: [-0.5, 1.2] + }, + //4 + { + scale: [0.7, -1.0], + hoverScale: [0.5, -1.2] + }, + //5 + { + scale: [0, 1.5], + hoverScale: [0, 1.5] + }, + //6 + { + scale: [0.5, 0], + hoverScale: [0.6, 0] + }, + //7 + { + scale: [0.6, 1.5], + hoverScale: [0.7, 1.2] + }, + //8 + { + scale: [1.5,0.6], + hoverScale: [1.2, 0.7] + }, + //9 + { + scale: [2, 3], + hoverScale: [2, 3] + }, + //10 + { + scale: [0.4, 0.7], + hoverScale: [0.4, 0.7] + }, + ] + build() { + Scroll(this.scroller){ + Column({space: 5}) { + // previewAnimationOptions的scale和hoverScale + Text(`验证bindContextMenu入参opt的previewAnimationOptions`) + .paramTextStyle() + Column({space : 5}){ + Text(`bindContextMenu设置IMAGE预览图, 设置scale和hoverScale (预期不生效)`) + .paramTextStyle() + Image($r('app.media.app_icon')) + .key(`previewImage_setScaleAndHoverScale`) + .width('120').height(45) + .bindContextMenu(this.MenuBuilder(), ResponseType.LongPress, { + preview: MenuPreviewMode.IMAGE, + previewAnimationOptions: { + hoverScale: [0.5, 1.5], + scale: [0.5, 1.5] + } + }) + Text(`bindContextMenu不设置预览图, 设置scale和hoverScale`) + .paramTextStyle() + Image($r('app.media.app_icon')) + .key(`unsetPreview_setScaleAndHoverScale`) + .width('120').height(45) + .bindContextMenu(this.MenuBuilder(), ResponseType.LongPress, { + previewAnimationOptions: { + hoverScale: [0.5, 1.5], + scale: [0.5, 1.5] + } + }) + Image($r('app.media.app_icon')) + .key(`unsetPreview_setScaleAndHoverScale_1`) + .width('120').height(45) + .bindContextMenu(this.menuShow[1],this.MenuBuilder(), { + previewAnimationOptions: { + hoverScale: [0.5, 1.5], + scale: [0.5, 1.5] + }, + onDisappear: () => { + this.menuShow[1] = false + } + }) + .onClick( () => { + this.menuShow[1] = true + }) + Text(`bindContextMenu设置自定义预览图, 设置scale和hoverScale`) + .paramTextStyle() + Row({ space: 2 }) { + Text(`${this.index[0] + 1}` + ' / ') + .fontSize(9) + Text(`${this.menuPreviewAnimationOptionsTestList.length}`) + .key('paramSets_key_0') + .fontSize(9) + MyComponent({ + title: 'Test0+', func: () => { + this.index[0]++ + if (this.index[0] == this.menuPreviewAnimationOptionsTestList.length) { + this.index[0] = 0 + } + } + }) + MyComponent({ + title: 'Test0-', func: () => { + this.index[0]-- + if (this.index[0] <= -1) { + this.index[0] = this.menuPreviewAnimationOptionsTestList.length - 1 + } + } + }) + } + Row({ space: 2 }) { + Text(`${this.index[1] + 1}` + ' / ') + .fontSize(9) + Text(`${this.menuPreviewAnimationOptionsTestList.length}`) + .key('paramSets_key_1') + .fontSize(9) + MyComponent({ + title: 'Test1+', func: () => { + this.index[1]++ + if (this.index[1] == this.menuPreviewAnimationOptionsTestList.length) { + this.index[1] = 0 + } + } + }) + MyComponent({ + title: 'Test1-', func: () => { + this.index[1]-- + if (this.index[1] <= -1) { + this.index[1] = this.menuPreviewAnimationOptionsTestList.length - 1 + } + } + }) + } + Image($r('app.media.app_icon')) + .key(`setPreview_setScaleAndHoverScale`) + .width('120').height(45) + .bindContextMenu(this.MenuBuilder(), ResponseType.LongPress, { + preview: this.MenuPreviewBuilder(), + previewAnimationOptions: { + scale: this.menuPreviewAnimationOptionsTestList[this.index[0]]?.scale, + hoverScale: this.menuPreviewAnimationOptionsTestList[this.index[1]]?.hoverScale, + } + }) + Image($r('app.media.app_icon')) + .key(`setPreview_setScaleAndHoverScale_1`) + .width('120').height(45) + .bindContextMenu(this.menuShow[2], this.MenuBuilder(), { + preview: this.MenuPreviewBuilder(), + previewAnimationOptions: { + scale: this.menuPreviewAnimationOptionsTestList[this.index[0]]?.scale, + hoverScale: this.menuPreviewAnimationOptionsTestList[this.index[1]]?.hoverScale, + }, + onDisappear: () => { + this.menuShow[2] = false + } + }) + .onClick( () => { + this.menuShow[2] = true + }) + } + .columnStyle() + } + .width('100%') + } + .padding(12) + .align(Alignment.TopStart) + .width('100%').height('100%') + } +} \ No newline at end of file diff --git a/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_24.ets b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_24.ets new file mode 100644 index 0000000000000000000000000000000000000000..d713cbd965f07cdc99858170dce2efaa378b3189 --- /dev/null +++ b/examples/Menu/entry/src/main/ets/pages/Examples/MenuTestLevel0_24.ets @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * bindContextMenu设置预览图菜单 + * 预览图菜单的预览图缩放方式/预览图宽高布局区域 + */ + +import { MyComponent } from '../../common/MyComponent' +import { SimpleMenuBuilder, MenuAttrOptions } from '../../customBuilder/MenuBuilder' + +@Extend(Text) +function paramTextStyle() { + .fontSize(11) + .width('100%') +} + +@Extend(Text) +function componentTextStyle() { + .fontSize(15) + .backgroundColor(Color.Orange) + .margin(3) + .padding(3) + .borderWidth(1.0) +} + +@Extend(Column) +function columnStyle() { + .backgroundColor(Color.Pink) + .width('100%') + .borderWidth(1.0) + .padding(5) +} + +@Extend(Select) +function selectStyle() { + .width('50%') + .controlSize(ControlSize.SMALL) + .selected(0) + .backgroundColor(Color.Orange) +} + +@Entry +@Component +struct MenuTestLevel0_24 { + scroller: Scroller = new Scroller() + @State index: number[] = [0, 0, 0] + @State menuOption: ContextMenuOptions = {} + //column的对齐方式 + @State columnAlignHorizontal: HorizontalAlign = HorizontalAlign.Start + @State columnAlignFlex: FlexAlign = FlexAlign.Start + // + @State menuShow: boolean[] = [false, false] + //Menu的builder option + @State menuAttrOption: MenuAttrOptions = { + submenuMode: 0 + } + @State menuBuilderWidth: number = 160 + @State menuBuilderHeight: number = 120 + + @Builder + MenuBuilder() { + SimpleMenuBuilder({ menuAttrOptions: { submenuMode: this.menuAttrOption.submenuMode } }) + .width(this.menuBuilderWidth) + .height(this.menuBuilderHeight) + } + + // 菜单的预览图 + @State previewWidth: number | string = 120 + @State previewHeight: number | string = 120 + + @Builder + MenuPreviewBuilder() { + Image($r('app.media.app_icon')) + .width(this.previewWidth) + .height(this.previewHeight) + } + + // 菜单控制的opt + @State contextMenuOptions: ContextMenuOptions = {} + + build() { + Stack() { + // bindMenu绑定组件区域 + Scroll() { + Column() { + Column() { + } + .backgroundColor('#ff848f6b') + .height(20).width(20) + .bindContextMenu(this.menuShow[0], this.MenuBuilder(), { + previewScaleMode: this.menuOption.previewScaleMode, + availableLayoutArea: this.menuOption.availableLayoutArea, + layoutRegionMargin: this.contextMenuOptions.layoutRegionMargin, + preview: this.MenuPreviewBuilder(), + onDisappear: () => { + this.menuShow[0] = false + } + }) + } + .alignItems(this.columnAlignHorizontal) + .justifyContent(this.columnAlignFlex) + .width('100%').height('100%') + } + .padding({ + top: 10, + bottom: 10, + left: 16, + right: 16 + }) + .width('100%') + .height('100%') + .backgroundColor(Color.Transparent) + + // 控制区域 + Scroll(this.scroller) { + Column({ space: 5 }) { + Text('验证菜单预览图') + .paramTextStyle() + Column({ space: 5 }) { + Text(`切换绑定组件的位置`) + .paramTextStyle() + Select([ + { value: 'TopStart' }, + { value: 'TopCenter' }, + { value: 'TopEnd' }, + { value: 'CenterStart' }, + { value: 'Center' }, + { value: 'CenterEnd' }, + { value: 'BottomStart' }, + { value: 'BottomCenter' }, + { value: 'BottomEnd' }, + ]) + .value('TopStart') + .selected(0) + .selectStyle() + .onSelect((idx, value: string) => { + switch (value) { + case 'TopStart': + this.columnAlignFlex = FlexAlign.Start + this.columnAlignHorizontal = HorizontalAlign.Start + break; + case 'TopCenter': + this.columnAlignFlex = FlexAlign.Start + this.columnAlignHorizontal = HorizontalAlign.Center + break; + case 'TopEnd': + this.columnAlignFlex = FlexAlign.Start + this.columnAlignHorizontal = HorizontalAlign.End + break; + case 'CenterStart': + this.columnAlignFlex = FlexAlign.Center + this.columnAlignHorizontal = HorizontalAlign.Start + break; + case 'Center': + this.columnAlignFlex = FlexAlign.Center + this.columnAlignHorizontal = HorizontalAlign.Center + break; + case 'CenterEnd': + this.columnAlignFlex = FlexAlign.Center + this.columnAlignHorizontal = HorizontalAlign.End + break; + case 'BottomStart': + this.columnAlignFlex = FlexAlign.End + this.columnAlignHorizontal = HorizontalAlign.Start + break; + case 'BottomCenter': + this.columnAlignFlex = FlexAlign.End + this.columnAlignHorizontal = HorizontalAlign.Center + break; + case 'BottomEnd': + this.columnAlignFlex = FlexAlign.End + this.columnAlignHorizontal = HorizontalAlign.End + break; + } + }) + .key('select_targetCompPos') + Text(`切换次级菜单类型: ${this.menuAttrOption.submenuMode}`) + .paramTextStyle() + Row({ space: 3 }) { + MyComponent({ + title: 'SIDE', func: () => { + this.menuAttrOption.submenuMode = SubMenuExpandingMode.SIDE_EXPAND + } + }) + MyComponent({ + title: 'EMBEDDED', func: () => { + this.menuAttrOption.submenuMode = SubMenuExpandingMode.EMBEDDED_EXPAND + } + }) + MyComponent({ + title: 'STACK', func: () => { + this.menuAttrOption.submenuMode = SubMenuExpandingMode.STACK_EXPAND + } + }) + } + + Text(`切换菜单预览图宽度: ${this.previewWidth}`) + .paramTextStyle() + Select([ + { value: '80%' }, + { value: '85%' }, + { value: '90%' }, + { value: '95%' }, + { value: '100%' }, + { value: '120' }, + { value: '240' }, + { value: '320' }, + { value: '400' }, + ]) + .selected(4) + .selectStyle() + .onSelect((idx, value: string) => { + this.previewWidth = value + }) + .key('select_menuPreviewWidth') + Text(`切换菜单预览图高度: ${this.previewHeight}`) + .paramTextStyle() + Select([ + { value: '80%' }, + { value: '85%' }, + { value: '90%' }, + { value: '95%' }, + { value: '100%' }, + { value: '120' }, + { value: '240' }, + { value: '480' }, + { value: '600' }, + { value: '840' }, + ]) + .selected(4) + .selectStyle() + .onSelect((idx, value: string) => { + this.previewHeight = value + }) + .key('select_menuPreviewHeight') + Text(`切换菜单宽度: ${this.menuBuilderWidth}`) + .paramTextStyle() + Slider({ + value: this.menuBuilderWidth!!, + min: 120, + max: 240, + step: 20 + }) + .showSteps(true) + .onChange((value: number, mode: SliderChangeMode) => { + this.menuBuilderWidth = value + }) + .id('sliderMenuBuilderWidth') + Text(`切换菜单高度: ${this.menuBuilderHeight}`) + .paramTextStyle() + Slider({ + value: this.menuBuilderHeight!!, + min: 80, + max: 240, + step: 40 + }) + .showSteps(true) + .onChange((value: number, mode: SliderChangeMode) => { + this.menuBuilderHeight = value + }) + .id('sliderMenuBuilderHeight') + Text(`切换预览图的安全边距: ${this.contextMenuOptions.layoutRegionMargin}`) + .paramTextStyle() + Row({ space: 3 }) { + MyComponent({ + title: '默认边界边距', func: () => { + this.contextMenuOptions.layoutRegionMargin = undefined + } + }) + MyComponent({ + title: 'margin: 60', func: () => { + this.contextMenuOptions.layoutRegionMargin = { + top: 60, + bottom: 60, + left: 60, + right: 60 + } + } + }) + } + } + .columnStyle() + + Column({ space: 5 }) { + Text(`选择预览图缩放模式`) + .paramTextStyle() + Select([ + { value: 'PreviewScaleMode.AUTO' }, + { value: 'PreviewScaleMode.CONSTANT' }, + { value: 'PreviewScaleMode.MAINTAIN' }, + ]) + .selected(0) + .selectStyle() + .onSelect((idx, value: string) => { + switch (value) { + case 'PreviewScaleMode.AUTO': + this.menuOption.previewScaleMode = PreviewScaleMode.AUTO + break; + case 'PreviewScaleMode.CONSTANT': + this.menuOption.previewScaleMode = PreviewScaleMode.CONSTANT + break; + case 'PreviewScaleMode.MAINTAIN': + this.menuOption.previewScaleMode = PreviewScaleMode.MAINTAIN + break; + } + }) + .key('select_menuPreviewScaleMode') + Text(`选择预览图宽高的可布局区域`) + .paramTextStyle() + Select([ + { value: 'undefined' }, + { value: 'AvailableLayoutArea.SAFE_AREA' }, + ]) + .selected(0) + .selectStyle() + .onSelect((idx, value: string) => { + switch (value) { + case 'undefined': + this.menuOption.availableLayoutArea = undefined + break; + case 'AvailableLayoutArea.SAFE_AREA': + this.menuOption.availableLayoutArea = AvailableLayoutArea.SAFE_AREA + break; + } + }) + .key('select_menuAvailableLayoutArea') + Text('预览图菜单') + .componentTextStyle() + .onClick(() => { + this.menuShow[0] = true + }) + } + .columnStyle() + } + .width('100%') + } + .padding(24) + .align(Alignment.TopStart) + .width('100%').height('100%') + } + .alignContent(Alignment.Center) + .width('100%') + .height('100%') + } + + pageTransition() { + //进入该界面没有跳转延迟 + PageTransitionEnter({ type: RouteType.None, duration: 0 }) + } +} \ No newline at end of file diff --git a/examples/Menu/entry/src/main/resources/base/element/float.json b/examples/Menu/entry/src/main/resources/base/element/float.json index 33ea22304f9b1485b5f22d811023701b5d4e35b6..78b3e64f8a0acc93ca4c01fe5b4d45f055a6fa9f 100644 --- a/examples/Menu/entry/src/main/resources/base/element/float.json +++ b/examples/Menu/entry/src/main/resources/base/element/float.json @@ -3,6 +3,50 @@ { "name": "page_text_font_size", "value": "50fp" + }, + { + "name": "float_0", + "value": "0" + }, + { + "name": "float_10", + "value": "10" + }, + { + "name": "float_20", + "value": "20" + }, + { + "name": "float_30", + "value": "30" + }, + { + "name": "float_40", + "value": "40" + }, + { + "name": "float_50", + "value": "50" + }, + { + "name": "float_60", + "value": "60" + }, + { + "name": "float_70", + "value": "70" + }, + { + "name": "float_80", + "value": "80" + }, + { + "name": "float_90", + "value": "90" + }, + { + "name": "float_100", + "value": "100" } ] } diff --git a/examples/Menu/entry/src/main/resources/base/profile/main_pages.json b/examples/Menu/entry/src/main/resources/base/profile/main_pages.json index 585110a97b49d7cf25887ccbaf51332c1d5b85bf..9a892eafbeca95b1c29636246edef2fea4584a47 100644 --- a/examples/Menu/entry/src/main/resources/base/profile/main_pages.json +++ b/examples/Menu/entry/src/main/resources/base/profile/main_pages.json @@ -19,7 +19,11 @@ "pages/Examples/MenuTestLevel0_4", "pages/Examples/MenuTestLevel0_5", "pages/Examples/MenuTestLevel0_6", + "pages/Examples/MenuTestLevel0_12", + "pages/Examples/MenuTestLevel0_16", + "pages/Examples/MenuTestLevel0_17", "pages/Examples/MenuTestLevel0_18", + "pages/Examples/MenuTestLevel0_24", "pages/LifeCycle/Index", "pages/LifeCycle/aboutToAppear/BindMenu",