前言:
本案例將介紹如何封裝彈窗,以及如何使用這種封裝後的彈窗 效果圖預覽
效果圖預覽
使用講解
- 進入案例,點擊右上角篩選按鈕,頂部彈出篩選框,點擊一種文件類型進行篩選
- 點擊左上角添加按鈕,中間彈出新增文件彈框,輸入文件名以及選擇文件類型,點擊確定按鈕添加完畢
- 長按列表項出現彈窗,點擊刪除按鈕,中間彈出刪除確認框,點擊確認按鈕刪除完畢
- 長按列表項出現彈窗,底部彈出文件詳情彈框
實現思路
定義彈窗的父佈局builder,支持自定義彈窗內容傳入,設置彈窗蒙層。
@Builder
export function DialogBuilder(param: EncapsulateDialogBuilderParam) {
Stack({ alignContent: getAlignment(param.dialogType) }) {
Stack()
.width('100%')
.height('300%')
.backgroundColor(0x33000000)
.onClick(() => {
if (param.isModalClosedByOverlayClick) {
param.closeDialog!();
}
})
param.builder.builder({ onConfirm: param.onConfirm, closeDialog: param.closeDialog, data: param.data })
}.width('100%')
.height('100%')
}
使用openCustomDialog接口,該接口可支持傳入builder。
public static showCustomDialog(param: DialogParam): void {
if (!DialogUtil.uiContext) {
return;
}
let promptAction = DialogUtil.uiContext.getPromptAction();
let encapsulateParam: EncapsulateDialogBuilderParam = DialogUtil.transformDialogParamToEncapsulateDialogBuilderParam(param);
let compCont = new ComponentContent(DialogUtil.uiContext, wrapBuilder(DialogBuilder), encapsulateParam);
// 設置了彈窗id即可將其與彈窗關聯起來,後續可憑據彈窗id關閉彈窗
if (param.dialogId) {
DialogUtil.compContMap.set(param.dialogId, compCont);
}
DialogUtil.fillCancelMethod(encapsulateParam, promptAction, compCont, param.dialogId);
DialogUtil.fillConfirmMethod(encapsulateParam, promptAction, compCont, param.dialogId);
compCont.update(encapsulateParam);
let options: promptAction.BaseDialogOptions = DialogUtil.dealSlideToClose(param);
promptAction.openCustomDialog(compCont, options);
}
自定義關閉彈窗回調。
private static fillCancelMethod(param: EncapsulateDialogBuilderParam, promptAction: PromptAction,
compCont: ComponentContent<DialogParam>, dialogId: string | undefined) {
let customCancel = param.closeDialog;
let cancelDialog = () => {
if (customCancel) {
customCancel();
}
if (dialogId) {
DialogUtil.compContMap.delete(dialogId);
}
promptAction.closeCustomDialog(compCont);
// 關閉彈框之後釋放對應的ComponentContent
compCont.dispose();
};
param.closeDialog = cancelDialog;
}
- 自定義彈窗確認回調。
private static fillConfirmMethod(param: EncapsulateDialogBuilderParam, promptAction: PromptAction,
compCont: ComponentContent<DialogParam>, dialogId: string | undefined) {
let confirm = param.onConfirm;
let confirmDialog = (isCloseDialog?: boolean, data?: ESObject) => {
if (confirm) {
confirm(isCloseDialog, data);
}
if (isCloseDialog) {
if (dialogId) {
DialogUtil.compContMap.delete(dialogId);
}
promptAction.closeCustomDialog(compCont);
compCont.dispose();
}
};
param.onConfirm = confirmDialog;
}
- 自定義彈窗彈出動效。
/**
* 頂部彈出動畫
* @param duration 動畫時間
* @returns
*/
static transitionFromUp(duration: number = 200): TransitionEffect {
return TransitionEffect.asymmetric(
TransitionEffect.OPACITY.animation({ duration: duration }).combine(
TransitionEffect.move(TransitionEdge.TOP).animation({ duration: duration })),
TransitionEffect.OPACITY.animation({ delay: duration, duration: duration }).combine(
TransitionEffect.move(TransitionEdge.TOP).animation({ duration: duration }))
)
}
使用步驟
- 初始化DialogUtil,需調用其init方法將UIContext傳入。
aboutToAppear(): void {
DialogUtil.init(this.getUIContext());
...
}
- 定義彈窗builder,該builder必須有且只有DialogBuilderParam參數。
@Builder
export function addFileDialogBuilder(param: DialogBuilderParam) {
AddFileComponent({ param: param })
}
- 定義彈窗封裝組件,該組件內部必須有DialogBuilderParam參數且使用@Prop註解。
@Component
export struct AddFileComponent {
@Prop param: DialogBuilderParam;
...
}
- 以上就封裝好了自定義彈窗,接下來使用只需要調用一下showCustomDialog方法,將對應彈窗封裝的builder傳入。
showFileInfo(item: FileItem) {
// 打開篩選彈窗
DialogUtil.showCustomDialog({
builder: wrapBuilder(fileInfoDialogBuilder),
dialogType: DialogTypeEnum.BOTTOM,
dialogBuilderParam: {
data: item
}
})
}
總結:
- 本案例依賴動態路由模塊來實現頁面的動態加載。
如果您想系統深入地學習 HarmonyOS 開發或想考取HarmonyOS認證證書,歡迎加入華為開發者學堂:
請點擊→:HarmonyOS官方認證培訓