前言:

本案例將介紹如何封裝彈窗,以及如何使用這種封裝後的彈窗 效果圖預覽

效果圖預覽

HarmonyOS應用案例:彈窗封裝_自定義

使用講解

  1. 進入案例,點擊右上角篩選按鈕,頂部彈出篩選框,點擊一種文件類型進行篩選
  2. 點擊左上角添加按鈕,中間彈出新增文件彈框,輸入文件名以及選擇文件類型,點擊確定按鈕添加完畢
  3. 長按列表項出現彈窗,點擊刪除按鈕,中間彈出刪除確認框,點擊確認按鈕刪除完畢
  4. 長按列表項出現彈窗,底部彈出文件詳情彈框

實現思路

定義彈窗的父佈局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;
  }
  1. 自定義彈窗確認回調。
  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;
  }
  1. 自定義彈窗彈出動效。
  /**
 * 頂部彈出動畫
 * @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 }))
  )
}

使用步驟

  1. 初始化DialogUtil,需調用其init方法將UIContext傳入。
  aboutToAppear(): void {
    DialogUtil.init(this.getUIContext());
    ...
  }
  1. 定義彈窗builder,該builder必須有且只有DialogBuilderParam參數。
@Builder
export function addFileDialogBuilder(param: DialogBuilderParam) {
  AddFileComponent({ param: param })
}
  1. 定義彈窗封裝組件,該組件內部必須有DialogBuilderParam參數且使用@Prop註解。
@Component
export struct AddFileComponent {
  @Prop param: DialogBuilderParam;
  ...
}
  1. 以上就封裝好了自定義彈窗,接下來使用只需要調用一下showCustomDialog方法,將對應彈窗封裝的builder傳入。
  showFileInfo(item: FileItem) {
    // 打開篩選彈窗
    DialogUtil.showCustomDialog({
      builder: wrapBuilder(fileInfoDialogBuilder),
      dialogType: DialogTypeEnum.BOTTOM,
      dialogBuilderParam: {
        data: item
      }
    })
  }

總結:

  1. 本案例依賴動態路由模塊來實現頁面的動態加載。

如果您想系統深入地學習 HarmonyOS 開發或想考取HarmonyOS認證證書,歡迎加入華為開發者學堂:

請點擊→:HarmonyOS官方認證培訓