写点什么

【HarmonyOS】鸿蒙多 Toast 显示工具类

作者:zhongcx
  • 2024-10-11
    广东
  • 本文字数:4711 字

    阅读完需:约 15 分钟

【HarmonyOS】封装可以同时显示多个 toast 的工具类

src/main/ets/common/MyPromptActionUtil.ets

import { ComponentContent, PromptAction, window } from '@kit.ArkUI';import { BusinessError } from '@kit.BasicServicesKit';
// MyPromptInfo 类用于生成唯一的 dialogIDexport class MyPromptInfo { public dialogID: string
constructor() { this.dialogID = this.generateRandomString(10) }
// 生成指定长度的随机字符串 generateRandomString(length: number): string { const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; let result = '';
for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * characters.length); result += characters.charAt(randomIndex); }
return result; }}
// MyPromptActionUtil 类用于封装弹窗操作export class MyPromptActionUtil<T extends MyPromptInfo> { static myDialogPromptActionUtil: MyPromptActionUtil<MyToastInfo> | undefined = undefined
public static showToast(message: string) { if (!MyPromptActionUtil.myDialogPromptActionUtil) { //当前页面没显示toast // getContext().eventHub.off(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID) // MyPromptActionUtil.myDialogPromptActionUtil?.closeCustomDialog() //如果之前有的toast对话框,并且正在显示,则先关闭toast提示 window.getLastWindow(getContext()).then((windowClass) => { const uiContext = windowClass.getUIContext() MyPromptActionUtil.myDialogPromptActionUtil = new MyPromptActionUtil<MyToastInfo>(uiContext, wrapBuilder(myToastView), new MyToastInfo(message)) .setModal(false)//true:存在黑色半透明蒙层,false:没有蒙层 .setSwipeBackEnabled(false)//true:侧滑允许关闭弹窗 .setMaskTapToCloseEnabled(true)//true:点击半透明蒙层可关闭弹窗【注:如果setModal(false),那么就没有蒙层,所以点击对话框外也没有响应事件,也就是这里设置了也没效果,并且事件会穿透】 .setAlignment(DialogAlignment.Center) .onWillAppear(() => { console.info('在对话框的打开动画开始之前调用的回调函数') getContext().eventHub.on(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID, (data: string) => { //监听结果 if (data == '关闭弹窗') { MyPromptActionUtil.myDialogPromptActionUtil?.closeCustomDialog() } }) }) .onWillDisappear(() => { console.info('在对话框的关闭动画开始之前调用的回调函数') getContext().eventHub.off(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID) MyPromptActionUtil.myDialogPromptActionUtil = undefined }) .showCustomDialog() }) } else { //当前正在显示toast getContext().eventHub.emit(MyPromptActionUtil.myDialogPromptActionUtil.dialogID, { msg: message }) }
}
private uiContext: UIContext; private promptAction: PromptAction; private contentNode: ComponentContent<T> | undefined; private wrapBuilder: WrappedBuilder<[T]>; private t: T; private isModal: boolean = true; private alignment: DialogAlignment = DialogAlignment.Center; private isSwipeBackEnabled: boolean = true; private isMaskTapToCloseEnabled: boolean = true; public dialogID: string
constructor(uiContext: UIContext, wrapBuilder: WrappedBuilder<[T]>, t: T) { this.uiContext = uiContext; this.promptAction = uiContext.getPromptAction(); this.wrapBuilder = wrapBuilder; this.t = t; this.dialogID = t.dialogID }
setSwipeBackEnabled(isSwipeBackEnabled: boolean) { this.isSwipeBackEnabled = isSwipeBackEnabled; return this; }
setMaskTapToCloseEnabled(isMaskTapToCloseEnabled: boolean) { this.isMaskTapToCloseEnabled = isMaskTapToCloseEnabled return this; }
setAlignment(alignment: DialogAlignment) { this.alignment = alignment; return this; }
setModal(isModal: boolean) { this.isModal = isModal; return this; }
onDidAppear(callback: () => void) { this.onDidAppearCallback = callback; return this; }
onDidDisappear(callback: () => void) { this.onDidDisappearCallback = callback; return this; }
onWillAppear(callback: () => void) { this.onWillAppearCallback = callback; return this; }
onWillDisappear(callback: () => void) { this.onWillDisappearCallback = callback; return this; }
private onDidAppearCallback?: () => void; private onDidDisappearCallback?: () => void; private onWillAppearCallback?: () => void; private onWillDisappearCallback?: () => void;
closeCustomDialog() { if (this.contentNode) { this.promptAction.closeCustomDialog(this.contentNode); } return this; }
// 显示自定义弹窗 showCustomDialog() { try { if (!this.contentNode) { this.contentNode = new ComponentContent(this.uiContext, this.wrapBuilder, this.t); } this.promptAction.openCustomDialog(this.contentNode, { // 打开自定义弹窗 alignment: this.alignment, isModal: this.isModal, showInSubWindow: false, maskRect: { x: 0, y: 0, width: '100%', height: '100%' }, onWillDismiss: (dismissDialogAction: DismissDialogAction) => { //弹窗响应 console.info("reason" + JSON.stringify(dismissDialogAction.reason)) console.log("dialog onWillDismiss") if (dismissDialogAction.reason == 0 && this.isSwipeBackEnabled) { //手势返回时,关闭弹窗。 this.promptAction.closeCustomDialog(this.contentNode) } if (dismissDialogAction.reason == 1 && this.isMaskTapToCloseEnabled) { this.promptAction.closeCustomDialog(this.contentNode) } }, onDidAppear: this.onDidAppearCallback ? this.onDidAppearCallback : () => { }, onDidDisappear: this.onDidDisappearCallback ? this.onDidDisappearCallback : () => { }, onWillAppear: this.onWillAppearCallback ? this.onWillAppearCallback : () => { }, onWillDisappear: this.onWillDisappearCallback ? this.onWillDisappearCallback : () => { }, }); } catch (error) { // 错误处理 let message = (error as BusinessError).message; let code = (error as BusinessError).code; console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`); } return this; }}
class MyToastInfo extends MyPromptInfo { public message: string = ""
constructor(message: string) { super() this.message = message }}
@Builderfunction myToastView(data: MyToastInfo) { MyToastView({ dialogID: data.dialogID, message: data.message })}
@ObservedV2class ToastBean { message: string = "" @Trace isShow: boolean = true
constructor(message: string) { this.message = message }}
@Componentstruct MyToastView { @State toast_info_list: ToastBean[] = [] @Prop dialogID: string @Prop message: string
aboutToAppear(): void { this.toast_info_list.push(new ToastBean(this.message)) getContext().eventHub.on(this.dialogID, (data: object) => { if (data['msg']) { this.toast_info_list.push(new ToastBean(data['msg'])) } }) }
build() { Column() { ForEach(this.toast_info_list, (item: ToastBean) => { Text(item.message) .fontSize('36lpx') .fontColor(Color.White) .backgroundColor("#B2ff0000") .borderRadius(8) .constraintSize({ maxWidth: '80%' }) .padding({ bottom: '28lpx', left: '60lpx', right: '60lpx', top: '28lpx' }) .margin(5) .visibility(item.isShow ? Visibility.Visible : Visibility.None) .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { console.info('Test Text isVisible: ' + isVisible + ', currentRatio:' + currentRatio) if (isVisible && currentRatio >= 1.0) { setTimeout(() => { item.isShow = false }, 2000) } })
.animation({ duration: 200, onFinish: () => { console.info('==== onFinish') //动画结束后,判断数组是否已全部为隐藏状态,是的话证明所有toast内容都展示完成,可以释放全局弹窗了 let isAnimAll = true for (let i = 0; i < this.toast_info_list.length; i++) { if (this.toast_info_list[i].isShow == true) { //至少有一个正在显示 isAnimAll = false break; } } if (isAnimAll) { console.info('已展示完全部toast,为了性能,关闭弹窗释放view') getContext(this).eventHub.emit(this.dialogID, "关闭弹窗") } } }) .transition(TransitionEffect.OPACITY.animation({ duration: 200 })) })
} }}
复制代码

src/main/ets/pages/Page01.ets

import { MyPromptActionUtil } from '../common/MyPromptActionUtil'
@Entry@Componentstruct Page01 {
build() { Column() { Button('显示Toast').onClick(() => { MyPromptActionUtil.showToast(`随机数:${this.getRandomInt(1, 100)}`) }) } .width('100%') .height('100%') } getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; }}
复制代码


用户头像

zhongcx

关注

还未添加个人签名 2024-09-27 加入

还未添加个人简介

评论

发布
暂无评论
【HarmonyOS】鸿蒙多Toast显示工具类_zhongcx_InfoQ写作社区