ArkUI全局自定义弹窗解耦方案,不再依赖Page页面!

291 阅读2分钟

背景介绍:

我们App需要开发基础的权限库,且App多为Html5以及flutter页面。权限申请时需要展示自定义弹窗,系统的CustomDialog又依赖于struct组件。翻遍了官方文档找到了一种目前自测可以实现的方案供大家参考。

实现步骤:

  1. 创建子窗口依赖于windowStage: window.WindowStage对象,因此开发单例类,存储App的UIAbility创建的windowStage对象。
  2. 在UIAbility的onWindowStageCreate方法回调中,为单例类注入windoStage对象。也可AppStorage全局保存,使用时获取就不需要注入
onWindowStageCreate(windowStage: window.WindowStage): void {
  // Main window is created, set main page for this ability
  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  windowStage.loadContent('pages/Index', (err) => {
    if (err.code) {
      hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
      return;
    }
    PermissionManager.getInstance().initialize(windowStage);
    hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
  });
}
  1. 开发自定义弹窗UI,这里尤其要注意因为我们后面需要通过loadContent加载struct组件,因此@Entry修饰符中entryName需要赋值。如果有传参需求storage也需要声明具体参考如下:
xport const entryName: string = 'SingleDialog';

export const storageKey: string = 'SingleDialogPermission';

@Entry({ routeName: entryName, storage: LocalStorage.getShared() })
@Component
export struct SingleDialogStruct {
  @LocalStorageProp(storageKey) permission: PermissionData = new PermissionData();

  build() {
    Column() {
       .......此处是你自己的ui
    }
    .width('100%')
    .height('100%')
    //这里是自己模拟的Android弹窗背景遮罩
    .backgroundBrightness({ rate: 0.5, lightUpDegree: -0.1 })
    .justifyContent(FlexAlign.Center)
  }
}
  1. 调用window对应方法创建子window,同时通过loadContentByName传入子窗口(弹窗)要加载的UI以及数据
let storage: LocalStorage = this.createLocalStorage(permissions);
this.sub_windowClass?.loadContentByName(SingleDialog.entryName, storage, (err: BusinessError) => {});
  1. 设置子窗口背景透明,这里建议设置全屏,否则我们设置窗口背景遮罩时无法处理状态栏
this.sub_windowClass?.setWindowBackgroundColor('#00000000');
this.sub_windowClass?.setWindowTouchable(true);
this.sub_windowClass?.setWindowLayoutFullScreen(true);
  1. 调用showWindow展示弹窗即可,对应的取消也有destroy方法
调用showWindow展示弹窗即可,对应的取消也有destroy方法具体参考下面链接。

好了,以上就是我个人使用的一种弹窗解耦方案,大家如果有更好的方案欢迎共享一下。