场景描述
自定义弹窗是应用开发需要实现的基础功能,包括但不限于HarmonyOS开发者文档中定义的模态、半模态、Toast等形式,封装一个好用且和UI组件解耦的弹窗组件是开发者的高频诉求
自定义弹窗通常的使用场景有:
场景一:在公共逻辑中触发弹窗
登录提示弹窗、全屏广告弹窗、网络请求与其他操作行为的提示、异常弹窗
场景二:侧滑手势拦截
隐私弹窗的拦截,退出登录时的确认弹窗
场景三:切换页面弹窗不消失
隐私弹窗和二级页面中的半模态弹窗
场景四:自定义弹出、关闭动画
从下往上的抽屉式弹出、关闭时从上往下收回
场景五:透明、模态、半模态背景
应用实现自定义的背景颜色
方案描述
1. 使用Navigation.Dialog
基于Navigation.Dialog的透明页面特性,可以用于实现弹窗效果
而且Navigation.Dialog存在于路由栈中,天然可以实现切换页面弹窗不消失
当前限制:
弹窗组件中的动效建议开发者自行实现
Navigation.Dialog自身无颜色,需要开发者自行实现模态遮罩,以及手势事件。
演示效果:
对于少量弹窗的实现,可以直接使用Navigation来进行路由跳转,参考 Navigation常见场景及解决方案
其他Navigation
的使用也可参考上述文章
步骤一:封装路由工具类,并注册自定义弹窗组件
定义路由工具类AppRouter,并创建路由栈NavPathStack
export class AppRouter {
private static instance = new AppRouter();
private pathStack: NavPathStack = new NavPathStack(); // 初始化路由栈
public static getInstance(): AppRouter {
return AppRouter.instance;
}
public getPathStack(): NavPathStack {
return this.pathStack;
}
...
}
在根页面中注册NavPathStack
@Entry
@Component
struct Index {
build() {
Navigation(AppRouter.getInstance().getPathStack()) {
...
}
}
}
在.navDestination注册封装的自定义弹窗组件DefaultDialog
@Builder
PageMap(name: string) {
if (name === CommonConstants.DEFAULT_DIALOG) {
DefaultDialog()
}
...
}
Navigation(AppRouter.getInstance().getPathStack()) {
...
}.navDestination(this.PageMap)
进阶用法:可以参考动态路由案例实现动态路由, HarmonyOS NEXT应用开发案例集 - Gitee.com
步骤二:封装弹窗UI 组件
定义弹窗选项类AppDialogOption
export class AppDialogOption {
view?: WrappedBuilder<Object[]> // 自定义弹窗内容组件
buildParams?: Object // 自定义弹窗内容参数
params?: Object // 打开时传递参数
autoClose?: number // 自动关闭时间
onPop?: (data: PopInfo) => void // 接收上一个弹窗关闭时的参数回调
onBackPressed?: () => boolean // 侧滑返回拦截
styles?: AppDialogStyle = new AppDialogStyle() // 弹窗样式