全局Loading弹窗:用子窗口的形式来实现(HarmonyOS NEXT共享包依赖版)
【过时提醒】本篇文档所述创建loading弹窗的方式使用起来较为复杂,请参考下面方式:https://developer.huawei.com/consumer/cn/forum/topic/0203147021096254151?fid=0109140870620153026
因为自定义弹窗在按下返回键或ESC键后会消失,有时候并不能满足实际需求,所以考虑采用创建子窗口的方式来实现,子窗口天生对返回事件免疫。小生能力有限,欢迎各位方家指正。
【注】预览器下并无效果,请使用真机或模拟器测试~
1.创建共享包(如loadingLib,本示例在项目根目录下创建)
2.在loadingLib共享包中创建加载要显示的Page页面(LoadingPage.ets)
- 为LoadingPage指定路由名称,即:@Entry({ routeName: 'LoadingPage' })
@Entry({ routeName: 'LoadingPage' })
@Component
struct LoadingPage {
@StorageProp('loading_message') message: string = '请稍候'
build() {
Stack({ alignContent: Alignment.Center }) {
Column() {
LoadingProgress().width(30).height(30).color(Color.White)
Text(this.message ?? '请稍候')
.fontColor(Color.White)
.fontSize(16)
.margin({ top: 15 })
.width('100%')
.textAlign(TextAlign.Center)
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor('#88000000')
.borderRadius(8)
}
.width('100%')
.height('100%')
.backgroundColor(Color.Transparent)
}
}
3.创建LoadingUtils类用于创建子窗口(LoadingUtils.ts),需要导出
- 导入LoadingPage.ets页面:import 'loadingLib/src/main/ets/pages/LoadingPage.ets'
- 子窗口使用路由名称加载页面:await win.loadContentByName('LoadingPage')
- 在loadingLib共享包默认生成的Index.ets中导出LoadingUtils类:
export { LoadingUtils } from "./src/main/ets/utils/LoadingUtils"
- LoadingUtils代码如下:
import window from '@ohos.window';
import display from '@ohos.display';
import common from '@ohos.app.ability.common';
import UIAbility from '@ohos.app.ability.UIAbility';
import 'loadingLib/src/main/ets/pages/LoadingPage.ets'
/**
* 通过创建子窗口来显示Loading弹窗
*/
export class LoadingUtils {
private static EVENT_CREATE_SUB_WINDOW = 'createSubWindow'
private static EVENT_CLOSE_SUB_WINDOW = 'closeSubWindow'
static LOADING_MESSAGE = 'loading_message'
/**
* 发送创建loading子窗口的事件,显示loading
* @param context context
*/
static showLoading(context: common.UIAbilityContext, message: string = '请稍候') {
AppStorage.setOrCreate(LoadingUtils.LOADING_MESSAGE, message)
context?.eventHub.emit(LoadingUtils.EVENT_CREATE_SUB_WINDOW)
}
/**
* 发送关闭loading子窗口的事件,隐藏loading
* @param context context
*/
static hideLoading(context: common.UIAbilityContext) {
context?.eventHub.emit(LoadingUtils.EVENT_CLOSE_SUB_WINDOW)
}
/**
* 订阅创建和关闭loading子窗口的事件
* @param ability ability
* @param stage stage
*/
static subscribeLoadingEvent(ability: UIAbility, stage: window.WindowStage) {
if (ability) {
ability.context.eventHub.on(LoadingUtils.EVENT_CREATE_SUB_WINDOW, () => LoadingUtils.showSubWindow(stage))
ability.context.eventHub.on(LoadingUtils.EVENT_CLOSE_SUB_WINDOW, () => LoadingUtils.closeSubWindow(stage))
}
}
/**
* 取消订阅创建和关闭loading子窗口的事件
* @param ability ability
*/
static unsubscribeLoadingEvent(ability: UIAbility) {
if (ability) {
ability.context.eventHub.off(LoadingUtils.EVENT_CREATE_SUB_WINDOW)
ability.context.eventHub.off(LoadingUtils.EVENT_CLOSE_SUB_WINDOW)
}
}
/**
* 显示loading子窗口
* @param stage stage
*/
static async showSubWindow(stage: window.WindowStage) {
stage?.createSubWindow('sub_window').then(async win => {
// 设置子窗口显示的页面
await win.loadContentByName('LoadingPage')
// 设置全屏
let d = display.getDefaultDisplaySync()
let windowClass = stage.getMainWindowSync()
await win.setWindowSystemBarEnable([])
await win.setWindowLayoutFullScreen(true)
await win.resize(d.width, d.height)
// 设置半透明效果
win.setWindowBackgroundColor('#88000000')
win.showWindow()
})
}
/**
* 关闭loading子窗口
* @param stage stage
*/
static closeSubWindow(stage: window.WindowStage) {
stage?.getSubWindow().then(win => {
if (win.length > 0) {
win[0].destroyWindow()
}
})
}
}
4.在需要使用loadingLib共享包的module(如entry)中配置oh-package.json5依赖:
{
"name": "entry",
...
"dependencies": {
...
"loadingLib": "file:../loadingLib"
}
}
5.根据UIAbility生命周期回调,实现子窗口事件订阅与取消
- 方案1:创建MyAbilityStage.ets并配置:
export default class MyAbilityStage extends AbilityStage {
onCreate() {
this.context.getApplicationContext().on('abilityLifecycle', this.abilityLifecycleCallback)
}
/**
* 声明ability生命周期回调,需配置所有回调后才可以在applicationContext注册
*/
abilityLifecycleCallback: AbilityLifecycleCallback = {
onAbilityCreate(ability: UIAbility) {},
onWindowStageCreate(ability: UIAbility, windowStage: window.WindowStage) {
// 订阅子窗口事件
LoadingUtils.subscribeLoadingEvent(ability, windowStage)
},
onWindowStageActive(ability: UIAbility, windowStage: window.WindowStage) {},
onWindowStageInactive(ability: UIAbility, windowStage: window.WindowStage) {},
onWindowStageDestroy(ability: UIAbility, windowStage: window.WindowStage) {
LoadingUtils.unsubscribeLoadingEvent(ability)
},
onAbilityDestroy(ability: UIAbility) {},
onAbilityForeground(ability: UIAbility) {},
onAbilityBackground(ability: UIAbility) {},
onAbilityContinue(ability: UIAbility) {}
}
}
"module": {
...
"srcEntry": './ets/MyAbilityStage.ets',
...
}
- 方案2:直接在UIAbility中引用LoadingUtils类:
export default class YourAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
...
LoadingUtils.subscribeLoadingEvent(this, windowStage)
}
onWindowStageDestroy(): void {
LoadingUtils.unsubscribeLoadingEvent(this)
}
}
6.在Page或组件中使用:
- 显示loading:
LoadingUtils.showLoading(getContext(this) as common.UIAbilityContext, '加载中')
- 隐藏loading:
LoadingUtils.hideLoading(getContext(this) as common.UIAbilityContext)
7
9
43
浏览3737 编辑于2024-06-05 01:56天津
全部评论
最多点赞
最新发布
最早发布
写回答
- 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
- 如您发布的内容为转载内容,请注明内容来源。
发表
我要发帖子
了解社区公约,与您携手共创和谐专业的开发者社区。