# LvDialog **Repository Path**: lv_nanqing/LvDialog ## Basic Information - **Project Name**: LvDialog - **Description**: 鸿蒙的通用弹窗封装,可只通过builder构建属于你的弹窗布局样式 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 0 - **Created**: 2024-06-26 - **Last Updated**: 2025-06-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 弹窗能力 ***提供一种弹窗封装能力以及一些基础的弹窗,与页面进行解耦,使用简单,支持使用builder构建弹窗布局样式(当弹窗逻辑特别复杂时可以自定义一个弹窗组件然后放入builder里,[示例写法点这里](#实现复杂逻辑弹窗方法)),支持自定义弹窗关闭回调, 支持自定义点击事件回调,支持设置点击蒙层是否关闭弹窗,且支持定制侧滑事件,支持弹窗外部关闭弹窗,使用时只需要show一下就ok了,[使用示例代码点这里](https://gitee.com/lv_nanqing/lvdialog/blob/main/entry/src/main/ets/pages/Index.ets),示例如下*** ![](./lvdialog/lvdialog_demo.gif) ## 下载安装 ```shell ohpm install @lvnanqing/lvdialog ``` ## 使用说明 1、先在项目引入本库 ````javascript import { DialogUtil, DialogBuilderParam, DialogParam } from '@lvnanqing/lvdialog' ```` 2、在EntryAbility中初始化DialogUtil, 如下所示 ```typescript onWindowStageCreate(windowStage: window.WindowStage): void { ... windowStage.loadContent('pages/Index', (err) => { ... DialogUtil.setUIContext(windowStage.getMainWindowSync().getUIContext()); }); } ``` 3、定义弹窗样式 ```typescript import { DialogBuilderParam } from 'lvdialog' @Builder export function MyBuilder(param: DialogBuilderParam) { Column() { Text('我是测试弹窗') .fontSize(20) Button('点我关闭弹窗') .onClick(() => { param.closeDialog!(); }) Button('点击事件') .onClick(() => { param.onConfirm!(true, "我被点击了"); }) }.height('40%') .backgroundColor(Color.White) .width('100%') .justifyContent(FlexAlign.Center) } ``` 4、其中DialogBuilderParam结构如下: ```typescript export interface DialogBuilderParam { closeDialog?: () => void; // 自定义弹窗关闭回调 onConfirm?: (isCloseDialog?: boolean, data?: ESObject) => void; // 自定义点击事件回调 data?: ESObject; // 自定义内容 } ``` 5、使用DialogUtil的showCustomDialog方法使弹窗生效,其参数是DialogParam,结构如下: ```typescript export interface DialogParam { dialogId?: string; // 弹窗id(只有配置此项才能使用弹窗外部关闭弹窗的能力) builder: WrappedBuilder<[DialogBuilderParam]>; // 自定义弹窗样式 dialogType: DialogTypeEnum; // 弹窗类型:底部弹窗,顶部弹窗,中间弹窗 dialogBuilderParam?: BuilderParam; // 弹窗的参数 isModalClosedByOverlayClick?: boolean; // 点击蒙层是否关闭弹窗,默认为true/点击蒙层关闭弹窗 isSlideToClose?: boolean; // 控制侧滑是否关闭弹窗,默认为true/侧滑关闭弹窗 slideCallback?: () => void; // 侧滑回调 } ``` 6、其中BuilderParam结构如下: ```typescript export interface BuilderParam { closeDialog?: () => void; // 自定义弹窗关闭回调 onConfirm?: (data?: ESObject) => void; // 自定义点击事件回调 data?: ESObject; // 自定义内容 } ``` 6、使用案例如下: ```typescript Text('底部弹窗') .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { DialogUtil.showCustomDialog({ builder: wrapBuilder(MyBuilder), dialogType: DialogTypeEnum.BOTTOM, builderParam: { closeDialog: () => { console.log("关闭弹窗回调触发") }, onConfirm: (data?: ESObject) => { console.log("点击事件回调触发,data: {}" + JSON.stringify(data)); } } }) }) ``` 7、支持设置点击蒙层是否关闭弹窗, 只需设置isModalClosedByOverlayClick即可,默认为true,即点击蒙层关闭弹窗 ```typescript Text('点击蒙层不关闭弹窗的弹窗') .fontSize(20) .fontWeight(FontWeight.Bold) .onClick(() => { DialogUtil.showCustomDialog({ isModalClosedByOverlayClick: false, // 设置点击蒙层不关闭弹窗 builder: wrapBuilder(MyBuilder), dialogType: DialogTypeEnum.BOTTOM, builderParam: { closeDialog: () => { console.log("关闭弹窗回调触发") }, onConfirm: (data?: ESObject) => { console.log("点击事件回调触发,data: " + JSON.stringify(data)); } } }) }) ``` 8、支持设置侧滑是否关闭弹窗,只需设置isSlideToClose即可,默认为true,即侧滑关闭弹窗,且支持侧滑事件触发回调,使用案例如下: ```typescript Text('侧滑不关闭弹窗的弹窗') .fontSize(20) .fontWeight(FontWeight.Bold) .onClick(() => { DialogUtil.showCustomDialog({ isSlideToClose: false, // 设置侧滑不关闭弹窗 builder: wrapBuilder(MyBuilder), dialogType: DialogTypeEnum.BOTTOM, slideCallback: () => { console.log("侧滑回调触发"); }, builderParam: { closeDialog: () => { console.log("关闭弹窗回调触发"); }, onConfirm: (data?: ESObject) => { console.log("点击事件回调触发,data: " + JSON.stringify(data)); } } }) }) ``` 9、支持在弹窗外部关闭弹窗,只需要在show弹窗时同步设置弹窗id,即可通过closeCustomDialogById函数来关闭弹窗,使用案例如下: ```typescript Text('3s后自动关闭弹窗') .fontSize(20) .fontWeight(FontWeight.Bold) .onClick(() => { let dialogId: string = '123'; setTimeout(() => { DialogUtil.closeCustomDialogById(dialogId); }, 3000) DialogUtil.showCustomDialog({ isSlideToClose: false, // 设置侧滑不关闭弹窗 builder: wrapBuilder(MyBuilder), dialogType: DialogTypeEnum.BOTTOM, dialogId: dialogId }) }) ``` #### 实现复杂逻辑弹窗方法 - 首先自定义组件,在自定义组件里实现复杂的弹窗逻辑,如状态变量等。***注意事项***:需要在自定义组件中定义这个成员变量: ```typescript @Prop param: DialogBuilderParam; ``` - 以时间滑动选择弹窗举例,自定义一个时间滑动选择组件,实现如时间滑动变化等复杂逻辑,代码如下([详细代码点这](https://gitee.com/lv_nanqing/lvdialog/blob/main/lvdialog/src/main/ets/component/DateSlideSelector.ets)): ```typescript @Component export struct DateSlideSelector { @Prop param: DialogBuilderParam; @State @Watch("refreshMonthDatasource") selectYear: SlideData = new SlideData(2024); @State @Watch("refreshDayDataSource") selectMonth: SlideData = new SlideData(1); ... aboutToAppear(): void { ... } initDataSource() { ... } refreshMonthDatasource() { let tMaxMonth: number = 12; let tMinMonth: number = 1; ... this.refreshDayDataSource(); } refreshDayDataSource() { let tMaxDay: number = new Date(this.selectYear.data, this.selectMonth.data, 0).getDate(); let tMinDay: number = 1; ... } changeState(date: Date) { ... } build() { Column() { ... }.width('100%') .backgroundColor(Color.White) .height('25%') } @Builder slideSelector($$: SlideSelectorParam) { Stack() { ... }.width('30%') } } ``` - 其次定义builder,将自定义的弹窗组件放入builder中,这里就会涉及到上述注意事项里的必须定义DialogBuilderParam类型的变量, 这个变量是用来做数据传递以及弹窗控制的,统一格式如下代码所示: ```typescript /** * 日期滑动选择器 * @param param */ @Builder export function dateSlideSelectorBuilder(param: DialogBuilderParam) { DateSlideSelector({ param: param }) } ``` - 接下来就是把使用这个弹窗封装为接口了,这里需要使用DialogUtil的showCustomDialog接口,将我们上述步骤封装好的弹窗builder传入这个接口,代码如下: ```typescript /** * 时间滑动选择弹窗 * * @param getSelectTime 获取选择时间的回调函数 * @param param 定义时间滑动选择弹窗的当前选择时间以及最大时间最小时间,非必填,不填则默认 */ public static showDateSlideSelector(getSelectTime: (selectTime: number) => void, param?: DateSlideSelectorParam): void { DialogUtil.showCustomDialog({ builder: wrapBuilder(dateSlideSelectorBuilder), dialogType: DialogTypeEnum.BOTTOM, builderParam: { onConfirm: (data?: ESObject) => { getSelectTime(data); }, data: param } }); } ``` - 最后,我们可以在任何地方调用我们封装好的showDateSlideSelector接口来唤起时间弹窗,这样就实现了一个复杂逻辑的弹窗